インターフェースとTryGetComponent
CoddyのUnityジャーニー「Unityのゲームアーキテクチャ」セクションの一部。レッスン 8/64。
TryGetComponentは1回の呼び出しでコンポーネントを探し、見つかったかどうかを知らせます。インターフェースにも使えるため、接触した相手がダメージを受けるかどうかを調べる通常の方法です。この地雷は、IDamageableを実装している周囲のすべてのものにダメージを与えます。
public class Mine : MonoBehaviour
{
public float radius = 3f;
public int damage = 5;
void OnTriggerEnter(Collider other)
{
foreach (Collider c in Physics.OverlapSphere(transform.position, radius))
{
if (c.TryGetComponent(out IDamageable target))
{
target.TakeDamage(damage);
}
}
Destroy(gameObject);
}
}out IDamageable targetは、呼び出しの中で変数を宣言します。オブジェクトにIDamageableを実装するコンポーネントがある場合、TryGetComponentはtrueを返してtargetに値を設定します。そうでない場合はfalseを返し、targetはnullになります。調べるのはそのオブジェクトだけで、親や子は調べません。
GetComponentは、クラスがない場合とインターフェースがない場合とで異なる結果を返します。Editorでは、Rigidbodyがないオブジェクトに対してGetComponent<Rigidbody>()を呼び出すと、Unityの偽のnullが返されます。== nullはtrueになりますが、?.では検出できず、呼び出しはMissingComponentExceptionをスローします。インターフェースには偽のnullがありません。GetComponent<IDamageable>()は実際のC#のnullを返すため、== nullと?.のどちらも使えます。TryGetComponentを使えばどちらの場合もこの問題を避けられ、Editorではコンポーネントが見つからなくても何も割り当てられません。
チャレンジ
簡単Laser に Fire() を書きましょう。1本の光線で、4つの結果が起こります。
- 塔から
transform.forwardの方向に、長さrangeでPhysics.Raycastを飛ばします。外れた場合はMissedをログに出力します。 hit.collider.TryGetComponent(out IDamageable target)の場合は、TakeDamage(damage)を呼び出し、"Hit " + hit.collider.nameをログに出力します。- それ以外の場合、
Rigidbodyがあれば、AddForce(transform.forward * push, ForceMode.Impulse)を実行し、名前の前に"Pushed "を付けてログに出力します。なければ、名前の前に"Blocked by "を付けてログに出力します。
「プレイ」を押し、あらゆる方向に向きを変えて発射しましょう。その後、「確認」を押します。
自分で試してみよう
using UnityEngine;
using UnityEngine.InputSystem;
public class Laser : MonoBehaviour
{
public float range = 10f;
public int damage = 1;
public float push = 5f;
public float turnSpeed = 90f;
private InputAction moveAction;
void Start()
{
moveAction = InputSystem.actions.FindAction("Move");
}
void Update()
{
float turn = moveAction.ReadValue<Vector2>().x;
transform.Rotate(0f, turn * turnSpeed * Time.deltaTime, 0f);
if (Keyboard.current.spaceKey.wasPressedThisFrame)
{
Fire();
}
}
void Fire()
{
// 前方に長さがrange単位のレイを飛ばし、当たった対象を処理する
}
}
Unityのゲームアーキテクチャのすべてのレッスン
自分で練習してみよう: Unityプレイグラウンド