Unity的C#編程教程_58_Enums 詳解及應用練習

目錄:

C# Enums: Introduction

  • 枚舉的作用
    • 設定可讀取的選項
    • 不同的選項用 integer 表示

傳統的做法是,設計一個變數進行指示,比如 0 代表簡單,1 代表普通,2 代表困難,然後配合上判斷語句。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class SelectDifficulty : MonoBehaviour
{

    public int easy = 0;
    public int normal = 1;
    public int hard = 2;
    public int selectedDifficulty;


    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        
    }
}

另外一種更直觀的方法應該是,有個下拉列表 dropdown list,可以選擇0,1,2,分別對應 3 個難度等級。

比如設計一個難度選擇腳本 SelectDifficulty,掛載到 main camera 上:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class SelectDifficulty : MonoBehaviour
{

    public enum DifficultySelector
    {
        Easy, // 自動分配為 0,也可以手動設置指定的數值比如 Easy=13,
        Normal, // 自動分配為 1
        Hard // 自動分配為 2
    }

    public DifficultySelector selectedDifficulty; // 生成一個下拉框

    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        
    }
}

這樣在 inspector 中就可以看到一個 Selected Difficulty 的下拉框,裡面的選項是 Easy,Normal,Hard。

然後程式中就可以設置對應的分支了:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class SelectDifficulty : MonoBehaviour
{

    public enum DifficultySelector
    {
        Easy, // 自動分配為 0,也可以手動設置指定的數值比如 Easy=13,
        Normal, // 自動分配為 1
        Hard // 自動分配為 2
    }

    public DifficultySelector selectedDifficulty;

    // Start is called before the first frame update
    void Start()
    {
        /* 
        if(selectedDifficulty == DifficultySelector.Easy)
        {
            Debug.Log("Easy level");
        }
        else if(selectedDifficulty == DifficultySelector.Normal)
        {
            Debug.Log("Normal level");
        }
        else if(selectedDifficulty == DifficultySelector.Hard)
        {
            Debug.Log("Hard level");
        }
        */

        // 我們可以使用 if 判斷語句,但是更常用的搭配是 switch語句
        switch (selectedDifficulty)
        {
            case DifficultySelector.Easy:
                Debug.Log("Easy level");
                break;

            case DifficultySelector.Normal:
                Debug.Log("Normal level");
                break;

            case DifficultySelector.Hard:
                Debug.Log("Hard level");
                break;
        }
    }

    // Update is called once per frame
    void Update()
    {
        
    }
}

C# Enums: Enemy AI

  • 使用 Enum 來設計 Enemy AI
    • FSM:finite state machine
    • 敵人的不同狀態:比如巡邏模式,攻擊模式,死亡狀態等

創建一個腳本 EnemyAI:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class EnemyAI : MonoBehaviour
{
    public enum EnemyState // 創建一個 enum 來設置敵人的不同狀態
    {
        Patroling, // 巡邏狀態
        Attacking, // 攻擊狀態
        Chasing, // 追蹤狀態
        Death // 死亡狀態
    }

    public EnemyState currentState; // 當前狀態

    // Start is called before the first frame update
    void Start()
    {
        currentState = EnemyState.Patroling; // 初始化為巡邏狀態
    }

    // Update is called once per frame
    void Update()
    {
        switch (currentState)
        {
            case EnemyState.Patroling:
                //
                // 這裡設置該狀態下的 Enemy 的對應邏輯動作
                //
                break;

            case EnemyState.Attacking:
                //
                // 這裡設置該狀態下的 Enemy 的對應邏輯動作
                //
                break;

            case EnemyState.Chasing:
                //
                // 這裡設置該狀態下的 Enemy 的對應邏輯動作
                //
                break;

            case EnemyState.Death:
                //
                // 這裡設置該狀態下的 Enemy 的對應邏輯動作
                //
                break;
        }
    }
}

創建一個 Capsule 作為 Enemy,然後掛載上該腳本。

這樣就有了個切換開關,可以轉換 Enemy 的動作狀態了。

我們可以設置多個 Enemy,每個 Enemy 在不同情況下激活不同狀態。比如默認狀態是 Patroling,玩家接近到視野中的時候切換為 Attacking。

這裡我們嘗試手動切換:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class EnemyAI : MonoBehaviour
{
    public enum EnemyState // 創建一個 enum 來設置敵人的不同狀態
    {
        Patroling, // 巡邏狀態
        Attacking, // 攻擊狀態
        Chasing, // 追蹤狀態
        Death // 死亡狀態
    }

    public EnemyState currentState; // 當前狀態

    // Start is called before the first frame update
    void Start()
    {
        currentState = EnemyState.Patroling; // 初始化為巡邏狀態
    }

    // Update is called once per frame
    void Update()
    {
        switch (currentState)
        {
            case EnemyState.Patroling:
                //
                // 這裡設置該狀態下的 Enemy 的對應邏輯動作
                //
                break;

            case EnemyState.Attacking:
                //
                // 這裡設置該狀態下的 Enemy 的對應邏輯動作
                //
                break;

            case EnemyState.Chasing:
                //
                // 這裡設置該狀態下的 Enemy 的對應邏輯動作
                //
                break;

            case EnemyState.Death:
                //
                // 這裡設置該狀態下的 Enemy 的對應邏輯動作
                //
                break;
        }

        if (Input.GetKeyDown(KeyCode.P)) // 將 Enemy 設定為巡邏模式
        {
            currentState = EnemyState.Patroling;
        }
        else if(Input.GetKeyDown(KeyCode.A)) // 將 Enemy 設定為攻擊模式
        {
            currentState = EnemyState.Attacking;
        }
        else if (Input.GetKeyDown(KeyCode.C)) // 將 Enemy 設定為追蹤模式
        {
            currentState = EnemyState.Chasing;
        }
        else if (Input.GetKeyDown(KeyCode.D)) // 將 Enemy 設定為死亡狀態
        {
            currentState = EnemyState.Death;
        }
    }
}

我們也可以直接在 Switch 中設置切換:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class EnemyAI : MonoBehaviour
{
    public enum EnemyState // 創建一個 enum 來設置敵人的不同狀態
    {
        Patroling, // 巡邏狀態
        Attacking, // 攻擊狀態
        Chasing, // 追蹤狀態
        Death // 死亡狀態
    }

    public EnemyState currentState; // 當前狀態

    // Start is called before the first frame update
    void Start()
    {
        currentState = EnemyState.Patroling; // 初始化為巡邏狀態
    }

    // Update is called once per frame
    void Update()
    {
        switch (currentState)
        {
            case EnemyState.Patroling:

                if (Time.time > 5) // 遊戲運行 5 秒後轉化為攻擊模式
                {
                    currentState = EnemyState.Attacking;
                }

                break;

            case EnemyState.Attacking:
                //
                // 這裡設置該狀態下的 Enemy 的對應邏輯動作
                //
                break;

            case EnemyState.Chasing:
                //
                // 這裡設置該狀態下的 Enemy 的對應邏輯動作
                //
                break;

            case EnemyState.Death:
                //
                // 這裡設置該狀態下的 Enemy 的對應邏輯動作
                //
                break;
        }
    }
}

C# Enums: Custom Classes

  • 把 enum 和自定義的類結合起來
    • 為類設置屬性的下拉菜單

創建一個腳本命名為 Item:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[System.Serializable] // 在 Inspector 中可見
public class Item
{
    public string name;
    public int id;
    public Sprite icon;

    public enum ItemType // 道具所有類型
    {
        Weapon, // 武器
        Consumable, // 消耗品
        Others // 其他
    }

    public ItemType itemType; // 該道具類型

}

創建一個物品資料庫 ItemDatabase:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ItemDatabase : MonoBehaviour
{
    public List<Item> itemDatabase;

    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        
    }
}

掛載到 Main Camera 上面,設置 size,然後就可以編輯物品的資訊了,其中有個下拉框可以選擇物品類型。

不同的類型物品可以有不同的方法使用:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[System.Serializable] // 在 Inspector 中可見
public class Item
{
    public string name;
    public int id;
    public Sprite icon;

    public enum ItemType // 道具所有類型
    {
        Weapon,
        Consumable,
        Others
    }

    public ItemType itemType; // 該道具類型

    public void Action() // 每種道具有不同的使用方法
    {
        switch (itemType)
        {
            case ItemType.Weapon:
                Debug.Log("Attack"); // 武器用來攻擊
                break;

            case ItemType.Consumable:
                Debug.Log("Eat"); // 消耗品用來吃
                break;

            case ItemType.Others:
                Debug.Log("Nothing"); // 其他類型無法使用
                break;
        }
    }

}

遍歷物品來使用:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ItemDatabase : MonoBehaviour
{
    public List<Item> itemDatabase;

    // Start is called before the first frame update
    void Start()
    {
        foreach(var item in itemDatabase) // 遍歷物品資料庫
        {
            Debug.Log(item.name); // 列印物品名字
            item.Action(); // 執行物品對應的動作
        }
    }

    // Update is called once per frame
    void Update()
    {
        
    }
}

C# Enums: Casting Enums to Ints

  • 為 enum 的成員指定一個整型數字
    • 可以用來控制場景選擇

比如我們要使用 enum 來做關卡選擇,除了可以用對應的名字,可以用一個數字來選擇

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement; // 用於遊戲中場景控制的庫

public class LevelSelect : MonoBehaviour
{

    public enum Level
    {
        Level_1, // 默認對應 0
        Level_2, // 默認對應 1
        Level_3,
        Level_4
    }

    public Level currentLevel;

    // Start is called before the first frame update
    void Start()
    {
        currentLevel = Level.Level_1; // 初始化為第一關

        // 我們想要進入第一關的場景:
        SceneManager.LoadScene(0);
        // 場景選擇的輸入需要是個整型數字,所以這裡不能傳入 currentLevel
        // 所以我們可以改成下面的寫法:
        SceneManager.LoadScene((int)currentLevel);
        // 或者下面的寫法:
        SceneManager.LoadScene((int)Level.Level_1);
    }

    // Update is called once per frame
    void Update()
    {
        
    }
}

建立 4 個 Scenes,分別命名為:Level_1~Level_4,選擇 File – Build Settings,將 4 個場景文件拖拽到 Scenes In Build 窗口中,點擊 Build。

運行遊戲後,即進入了 Level_1 的場景。

Tags: