小さなコンポーネント
CoddyのUnityジャーニー「Unityのゲームアーキテクチャ」セクションの一部。レッスン 1/64。
GameObjectはコンポーネントのリストで、書くスクリプトはそれぞれコンポーネントを1つ追加します。Unityのゲームは、各スクリプトに1つの役割を持たせ、複数のスクリプトを1つのオブジェクトに付けて作ります。プレイヤーの移動、射撃、体力をすべて1つのPlayerControllerに含めることもできますが、Mover、Shooter、Healthの3つのコンポーネントに分ければ、それぞれをほかのオブジェクトにも付けられます。
public class Health : MonoBehaviour
{
public int hp = 3;
public void TakeDamage(int amount)
{
hp -= amount;
if (hp <= 0)
{
Destroy(gameObject);
}
}
}- Player:Mover、Shooter、Health
- Turret:Shooter、Health
- Crate:Health
通常のC#クラスでは、代わりに継承ツリーを作るかもしれません。Character、次にShootingCharacter : Character、そしてPlayer : ShootingCharacterです。タレットは射撃しますが歩くことはなく、クレートは壊れるだけなので、新しい種類のオブジェクトを作るたびにツリーを組み直すことになります。コンポーネントを使えば、新しい種類のオブジェクトは、すでにあるスクリプトを新しく組み合わせてInspectorで設定するだけです。また、各スクリプトにはそこで独自の値を設定できます。あるオブジェクトには遅いMoverを、別のオブジェクトには速いMoverを設定できます。
同じオブジェクト上のコンポーネントはTransformを共有するため、それぞれが変更するのは自分の担当部分だけにする必要があります。transform.position +=を使ってxとzに加算するMoverならyには触れないので、同じオブジェクト上のJumperが引き続き高さを変更できます。位置全体をnew Vector3(x, 0.5f, z)に設定するMoverでは、毎フレームyが元に戻され、ジャンプが打ち消されてしまいます。
チャレンジ
簡単Boat.cs を分割して、各スクリプトが1つの役割だけを担うようにしましょう。
- 上下運動を
Bobberに移します。Start()でstartYを設定し、独自のheightとspeedを使ってUpdate()で上下運動させます。 - 点滅処理を、独自のタイマーとともに
Blinkerに移します。 Boatから両方の処理とフィールドを削除し、操舵だけを行うようにします。
「プレイ」を押します。アヒルが上下に動き、ブイが点滅し、ボートが操舵されます。その後、「確認」を押します。
自分で試してみよう
using UnityEngine;
using UnityEngine.InputSystem;
// 1つのスクリプトで3つの役割:操舵、上下動、点滅。
public class Boat : MonoBehaviour
{
public float speed = 3f;
public float bobHeight = 0.1f;
public float bobSpeed = 2f;
public Renderer lamp;
public float blinkInterval = 0.5f;
private InputAction moveAction;
private float startY;
private float blinkTimer;
void Start()
{
moveAction = InputSystem.actions.FindAction("Move");
startY = transform.position.y;
}
void Update()
{
// 操舵
Vector2 input = moveAction.ReadValue<Vector2>();
transform.position += new Vector3(input.x, 0f, input.y) * speed * Time.deltaTime;
// 上下動
Vector3 p = transform.position;
p.y = startY + Mathf.Sin(Time.time * bobSpeed) * bobHeight;
transform.position = p;
// 点滅
blinkTimer += Time.deltaTime;
if (blinkTimer >= blinkInterval)
{
blinkTimer -= blinkInterval;
lamp.enabled = !lamp.enabled;
}
}
}
Unityのゲームアーキテクチャのすべてのレッスン
自分で練習してみよう: Unityプレイグラウンド