GetComponents
CoddyのUnityジャーニー「Unityにおけるゲームアーキテクチャ」セクションの一部。レッスン 8/50。
GetComponent<T>()は最初に一致したものを返します。GetComponents<T>()はオブジェクト上の一致したものすべてを配列として返し、GetComponentsInChildren<T>()はオブジェクト上とその配下にある一致したものすべてを返します。Tにインターフェースを指定すると、クラスに関係なく、何かを実行できるすべての部品を1回の呼び出しで取得できます。ここでは、工場の機械は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で行われます。1つのオブジェクトにLampとFanがある機械は、各コンポーネントが別々に一致するため、2つとして数えられます。Generatorはそれらの名前を指定しないため、後からFactoryの配下に追加されたIPoweredを実装するSirenも、次にSwitchを呼び出すと切り替わります。
GetComponentsInChildrenは呼び出し元のオブジェクトも含みます。また、trueを渡さない限り、非アクティブな子はスキップします。GetComponentsInChildren<IPowered>(true)のように指定します。GetComponentsはそのオブジェクト1つだけを調べるため、1つのドアにあるライトとブザーのように、隣り合って配置された部品に適しています。
チャレンジ
簡単トレーニング用ロボットは、攻撃を受けるたびに反応する必要があります。Robot の Health.cs は hp を数え、3つのパーツが反応します。Head の Flash は赤くなり、Robot の Recoil は後ろに跳ね、Antenna の Sparks は火花を散らします。Space キーでロボットに 1 のダメージを与え、クリックで 2 のダメージを与えます(Trainer.cs は準備済みです)。現時点では、Health は頭にしか伝えていません。
- IHitReaction.cs で、メソッド
void React(int damage)を1つ持つインターフェースIHitReactionを宣言します。 - Flash、Recoil、Sparks にこのインターフェースを実装させます。それぞれのメソッドを
React(int damage)にします。Flash はこれまでと同じ動作をします。Recoil はダメージ1ポイントにつき、ロボットを後方(+z方向)へ0.5単位跳ねさせ、Sparks はダメージ1ポイントにつき火花を1つ散らします。 - Health の
TakeDamageで、hp が減った後、Robot とその子にあるすべての IHitReaction にReact(amount)を呼び出します。1回の GetComponentsInChildren の呼び出しで取得し、反応した数をReactions: 3のようにログに出力します。
Play を押し、Space キーとクリックでロボットを攻撃してから、Check を押します。
自分で試してみよう
using UnityEngine;
public class Health : MonoBehaviour
{
public int hp = 10;
public void TakeDamage(int amount)
{
hp -= amount;
GetComponentInChildren<Flash>().Show();
}
}
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。