文章目录
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 的场景。