小さなコンポーネント
CoddyのUnityジャーニー「Unityにおけるゲームアーキテクチャ」セクションの一部。レッスン 1/50。
GameObject はコンポーネントのリストであり、あなたが書く各スクリプトもその一つです。Unity のゲームは、各スクリプトに一つの役割を持たせ、オブジェクトに複数のスクリプトを付けて作られます。プレイヤーの移動、射撃、ヒットポイントをすべて一つの 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);
}
}
}- プレイヤー: Mover、Shooter、Health
- タレット: Shooter、Health
- 木箱: 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 は一度に3つの役割を担っています。矢印キー(Move アクション)でボートを操縦し、ボートは波に揺れ、ランプが点滅します。アヒルにも揺れが必要で、ブイには揺れと点滅の両方が必要です。そのため、シーンにはすでに Bobber と Blinker コンポーネントが追加されており、ボートには3つすべてが追加されています。Boat.cs をこれらに分割しましょう。
- Bobber:それぞれのオブジェクトは、開始時の高さを基準に、独自の
speedでheight単位だけ上下に揺れます(Inspector で両方を設定します)。Bobber は位置の y だけを変更するため、ボートは引き続き操縦できます。 - Blinker:
lamp(Renderer)をinterval秒ごとに点灯・消灯します。 - Boat に残すのは操縦だけです。揺れと点滅、それらに関連するフィールドを削除します。
Play を押してボートを操縦し、次に Check を押してください。
自分で試してみよう
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;
}
}
}
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。