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 只会检查单个对象,适合检查并排放置的部件,例如同一扇门上的灯和蜂鸣器。
挑战
简单让机器人的每个部位都能对受击做出反应。
- 在
IHitReaction.cs中,声明public interface IHitReaction,并使用void React(int damage);。 - 让
Flash、Recoil和Sparks实现它:将每个方法重命名为public void React(int damage)。 Recoil向后移动0.5f * damage;Sparks抛出damage个火花。- 在
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 在线编辑器