IDamageable
CoddyのUnityジャーニー「Unityにおけるゲームアーキテクチャ」セクションの一部。レッスン 6/50。
ゲーム内でダメージを受けるものはたくさんありますが、共通点はほとんどありません。プレイヤーにはヒットポイントがあり、木箱は最初の攻撃で壊れます。共通の基底クラスを使うと、それらを1つの系統にまとめることになります。インターフェースは共通する点だけに名前を付け、それぞれのスクリプトが独自の方法で実装します。
public interface IDamageable
{
void TakeDamage(int amount);
}public class PlayerHealth : MonoBehaviour, IDamageable
{
public int hp = 10;
public void TakeDamage(int amount)
{
hp -= amount;
Debug.Log("Ouch! hp: " + hp);
}
}public class Crate : MonoBehaviour, IDamageable
{
public void TakeDamage(int amount)
{
Destroy(gameObject);
}
}スクリプトの基底クラスは引き続き1つで、MonoBehaviourを指定し、その後にインターフェースを列挙します。インターフェースは専用のファイルIDamageable.csに置き、MonoBehaviourを継承しません。コンポーネントではなく、単独でオブジェクトに付けることもありません。インターフェースを指定したクラスには、public TakeDamage(int)が必要です。そうでなければコンパイルできません。
ダメージを与える側は、クラスではなくインターフェースを要求します。
// Fireball.cs
void OnCollisionEnter(Collision collision)
{
IDamageable target = collision.gameObject.GetComponent<IDamageable>();
if (target != null)
{
target.TakeDamage(3);
}
Destroy(gameObject);
}この火の玉は同じコードでプレイヤーにダメージを与え、木箱を壊します。後から新しい種類の対象を追加しても、ここを変更する必要はありません。Unityではインターフェース型のフィールドはインスペクターに表示されないため、火の玉の例のように、スクリプトではGameObjectまたはコンポーネントを保持し、そこからインターフェースを取得します。
チャレンジ
簡単村の広場を巨人が守っています。矢印キーで巨人を動かし(Mover.cs、準備完了)、Spaceキーでハンマーを振ります。Hammer.cs は Slam() を呼び出し、radius 内のすべてのコライダーを見つけます。広場にある3つのものが、それぞれ異なる方法で攻撃を受け、ほかには何も共有しません。
Snowman:ダメージ1ポイントごとに、各軸のサイズが0.25ずつ小さくなります(最初のサイズは1.5です)。サイズが0.5以下になると溶けるので、雪だるまを破壊します。Bell:ダメージ1ポイントごとにDongを1回ログに出力し(2のダメージを受けると2回ログに出力)、そのポイント数をringsに加算します。Scarecrow:最初の攻撃で倒れ、ダメージ量にかかわらず、z軸を中心に90度回転します。その後の攻撃では何も変化しません。
IDamageable.cs で、メソッドを1つ持つインターフェースを宣言します:void TakeDamage(int amount)。Snowman、Bell、Scarecrow にこれを実装し、それぞれ独自の反応をさせます。次に、Slamで、見つかった各コライダーの IDamageable に対してTakeDamage(power)を呼び出します。地面など、IDamageable を持たないコライダーはスキップします。
Playを押し、それぞれのところまで歩いてハンマーを振り、次にCheckを押してください。
自分で試してみよう
using UnityEngine;
public class Snowman : MonoBehaviour
{
}
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。