Menu
CoddyTech

GetComponents

本课属于 Coddy Unity 学习旅程的“Unity 游戏架构”单元。第 9 课,共 64 课。

GetComponent<T>() 返回第一个匹配项。GetComponents<T>() 返回对象上的所有匹配项,并将它们作为数组返回;GetComponentsInChildren<T>() 则返回对象及其所有子对象上的所有匹配项。将接口用作 T 时,一次调用就能收集所有具备某种功能的部件,无论它们属于什么类。这里,工厂的机器是 Factory 对象的子对象,每个由电力驱动的部件都实现了 IPowered:

public interface IPowered
{
    void SetPower(bool on);
}
public class Generator : MonoBehaviour
{
    public GameObject factory;

    public void Switch(bool on)
    {
        IPowered[] parts = factory.GetComponentsInChildren<IPowered>();
        foreach (IPowered part in parts)
        {
            part.SetPower(on);
        }
        Debug.Log(parts.Length + " parts powered");
    }
}

Lamp 会切换自己的 Light,Fan 会开始转动,Conveyor 会开始移动,它们各自在自己的 SetPower 中完成这些操作。如果一台机器的同一个对象上有 Lamp 和 Fan,就会计为两项,因为每个组件都是单独的匹配项。Generator 不会指定这些部件,因此之后在 Factory 下添加一个实现 IPowered 的 Siren,下次调用 Switch 时它也会被打开。

GetComponentsInChildren 会包含调用它的对象,并跳过未激活的子对象,除非你传入 true:GetComponentsInChildren<IPowered>(true)。GetComponents 只会检查单个对象,适合检查并排放置的部件,例如同一扇门上的灯和蜂鸣器。

challenge icon

挑战

简单

让机器人的每个部位都能对受击做出反应。

  1. 在 IHitReaction.cs 中,声明 public interface IHitReaction,并使用 void React(int damage);。
  2. 让 Flash、Recoil 和 Sparks 实现它:将每个方法重命名为 public void React(int damage)。
  3. Recoil 向后移动 0.5f * damage;Sparks 抛出 damage 个火花。
  4. 在 TakeDamage 中,对每个 GetComponentsInChildren<IHitReaction>() 调用 React(amount),然后记录日志 Reactions: 3(它们的数量)。

按“开始”,按空格键,然后点击。接着点击“检查”。

亲手试试

using UnityEngine;

public class Health : MonoBehaviour
{
    public int hp = 10;

    public void TakeDamage(int amount)
    {
        hp -= amount;
        GetComponentInChildren<Flash>().Show();
    }
}

Unity 游戏架构中的所有课

自己练习: Unity 在线编辑器