抽象コンポーネント
CoddyのUnityジャーニー「Unityのゲームアーキテクチャ」セクションの一部。レッスン 3/64。
一部の基底クラスは、それ自体では決して存在しない種類のものを表します。すべての武器は発射しますが、ピストルでもショットガンでもない武器には発射する方法がありません。そのようなクラスにはabstractを付け、サブクラスが記述しなければならない各手順を、本文のない抽象メソッドとして宣言します。
public abstract class Weapon : MonoBehaviour
{
public int shots;
public void Pull()
{
shots++;
Fire();
}
protected abstract void Fire();
}public class Shotgun : Weapon
{
public GameObject pelletPrefab;
protected override void Fire()
{
for (int i = -1; i <= 1; i++)
{
Instantiate(pelletPrefab, transform.position + transform.right * i * 0.3f, transform.rotation);
}
}
}Fireを記述していないサブクラスはコンパイルできません。エラーはCS0534、'Pistol' does not implement inherited abstract member 'Weapon.Fire()'です。Unityも、オブジェクトに抽象スクリプトを追加することを拒否します。Weaponをオブジェクトにドラッグすると、Can't add script behaviour 'Weapon'. The script class can't be abstract!と表示されます。Fireを持たないWeaponをUnityは作成できないためです。
ほかのスクリプトは引き続き基底型を使えます。GetComponent<Weapon>()はオブジェクトに付いているサブクラスを返し、Pull()はそのサブクラスのFireを実行します。
// Player.cs
private Weapon weapon;
void Start()
{
weapon = GetComponent<Weapon>();
}
void Update()
{
if (Mouse.current.leftButton.wasPressedThisFrame)
{
weapon.Pull();
}
}ShotgunコンポーネントをPistolに差し替えても、Playerスクリプトはそのままです。
チャレンジ
簡単Monster を abstract にし、タワーがあらゆる種類のモンスターにザップを放つようにしましょう。
Monsterで、本文なしのpublic abstract class Monsterとprotected abstract void React();を書きます。- コンパイラーが
Impを指すようになります。protected override void React()を追加し、その位置にVector3.forward * 2fを加えます。 Towerのループ内で、target.GetComponent<Monster>()に対してZap()を呼び出します。
「プレイ」を押して Space を押します。スライムは縮み、インプは後ろに飛びます。その後、「確認」を押します。
自分で試してみよう
using UnityEngine;
// すべてのモンスターに共通するもの。
public class Monster : MonoBehaviour
{
public int hp = 3;
public void Zap()
{
hp--;
if (hp <= 0)
{
Destroy(gameObject);
}
else
{
React();
}
}
// この種類のモンスターが、生き延びた攻撃にどう反応するか。
protected virtual void React()
{
}
}
Unityのゲームアーキテクチャのすべてのレッスン
自分で練習してみよう: Unityプレイグラウンド