Menu
CoddyTech

检视面板中的枚举

本课属于 Coddy Unity 学习旅程的“Unity 游戏架构”单元。第 20 课,共 64 课。

枚举字段会在 Inspector 中显示为下拉菜单,因此很适合用来设置共用同一个脚本的对象。一个 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] 枚举可以同时保存多个值。它的下拉菜单会为每个值显示一个勾选项,另外还有“无”和“全部”。每个值都需要占用独立的一位,因此数字必须是 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。当 x 中的所有值都已设置时,HasFlag(x) 会返回 true;ToString() 会列出已设置的值,例如 Fire, Poison。

challenge icon

挑战

简单

让一扇门需要多张门卡,并让钥匙圈可以装多张门卡。

  1. 在 KeyRing.cs 中,将 [System.Flags] 放在 Access 上方,并将它们编号为 None = 0, Red = 1, Blue = 2, Green = 4。
  2. Add(Access card) 会保留已有的门卡:cards |= card;。
  3. 只有当钥匙圈里有 needs 中的每一张门卡时,Opens(Access 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;
    }
}

Unity 游戏架构中的所有课

自己练习: Unity 在线编辑器