Inspectorでの列挙型
CoddyのUnityジャーニー「Unityにおけるゲームアーキテクチャ」セクションの一部。レッスン 17/50。
enum フィールドは Inspector にドロップダウンとして表示されるため、1つのスクリプトを共有するオブジェクトを設定するのに便利です。1つの Pickup プレハブでコイン、ハート、シールドに対応できます。レベル内の各コピーはドロップダウンから種類を選び、スクリプトはその値に応じて処理を切り替えます:
public enum PickupKind { Coin, Heart, Shield }
public class Pickup : MonoBehaviour
{
public PickupKind kind;
public int amount = 1;
void OnTriggerEnter(Collider other)
{
if (!other.TryGetComponent(out PlayerStats stats)) return;
switch (kind)
{
case PickupKind.Coin: stats.coins += amount; break;
case PickupKind.Heart: stats.hp += amount; break;
case PickupKind.Shield: stats.shielded = true; break;
}
Destroy(gameObject);
}
}シーンは各選択肢を値の番号として保存します。Coin は 0、Heart は 1、Shield は 2 です。値を末尾に追加するのは安全です。{ Gem, Coin, Heart, Shield } のように先頭に挿入すると、すべての番号がずれて、すべてのシーンにあるすべてのピックアップの種類が変わります。値の名前を変更しても、番号はそのままなので安全です。Coin = 0, Heart = 1, Shield = 2 のように番号を明示しておけば、保存済みの選択肢を変えることなく、後から名前の順序を変更できます。
[System.Flags] enum には複数の値を同時に保持できます。ドロップダウンには各値のチェックボックスに加えて、Nothing と Everything が表示されます。各値には独自のビットが必要なので、番号には 2 の累乗を使います:
[System.Flags]
public enum Element { None = 0, Fire = 1, Ice = 2, Poison = 4 }
public Element immuneTo; // Inspectorでチェック済み: FireとPoison
public void Hit(int damage, Element element)
{
if (immuneTo.HasFlag(element)) return;
hp -= damage;
}| は値を組み合わせます。Element.Fire | Element.Poison は 5 です。HasFlag(x) は x 内のすべての値が設定されているときに true になり、ToString() は設定されている値を Fire, Poison のように列挙します。
チャレンジ
簡単基地には3つのドアがあります。物置には赤いキーカード、研究室には青いキーカード、金庫室には両方が必要です。各ドアのneedsと各カードのcardは、InspectorでAccess enumを使って設定済みで、Door.csとKeycard.csも準備できています。矢印キーでPlayerを動かし、PlayerのKeyRingには拾ったカードが入ります。KeyRing.csを完成させましょう。
- 複数の値を組み合わせられるenumとして
Accessを作り、ドアが複数のカードを必要とし、リングにも複数のカードを持たせられるようにします。4つの名前、None、Red、Blue、Greenはそのまま使います。 Add(Access card)は、すでにリングにあるカードを残したまま、カードをリングに追加します。Opens(Access needs)は、リングにneeds内のすべてのカードがあるときにtrueを返します。
プレイを押し、ドアを試し、カードを拾ってから、チェックを押しましょう。
自分で試してみよう
using UnityEngine;
public enum Access { None, Red, Blue, Green }
public class KeyRing : MonoBehaviour
{
public Access cards;
public void Add(Access card)
{
// すでにあるカードを残したまま、カードをリングに追加する
}
public bool Opens(Access needs)
{
// リングにneedsに含まれるすべてのカードがある場合はtrue
return false;
}
}
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。