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 的場景。