前篇链接:Unity之C#学习笔记(12):属性 Properties
还记得大一学C语言时,学到一大半被指针和链表绕的稀里糊涂之后老师讲了枚举和联合,当时也不太理解有什么用,而且看着也不像考点。后来开始写大一些的项目后才发现枚举确实是很实用的一个特性。
枚举(Enums)的作用其实很简单,就是提高程序的可读性,可理解性。一个简单的例子:你要设计一个游戏关卡,关卡有可选的四种难度(简单、普通、困难和专家),如何描述?第一个想法:使用4个bool值,isEasy,isNormal…值为true代表选择了对应难度。但这样做明显是不合理的,如果有两个值都被设置成了true呢?这其实本质上是丢失了多个值中只能选择一个的隐含条件。第二个想法,使用1个int值,用0,1,2,3代表难度。这样做是可以的,但当你的项目开始庞大起来,你还能随时记得哪个数字对应哪个难度吗?或者,你的同事在你的代码中看到一句if (level==1),会是什么心情?
枚举正如字面意义,就是用来描述这种多选一的值,而且让你看到的是容易理解的文字形式。在GameManager脚本中,我们先定义一个枚举类型:
public enum LevelSelect
{
Easy, // 0
Normal, // 1
Hard, // 2
Expert = 30
}
在底层上,编译器还是将枚举视为一个数字值,而且会自动按顺序赋予0,1,2…我们也可以通过赋值指明某个枚举值对应的数字。
声明一个LevelSelect类型的public变量:
public LevelSelect currentLevel;
然后在Unity面板中,可以看到:
出现了一个下拉框,可以从刚才自定义的枚举值中选择,看到的是我们声明的文字值。
枚举值的判断可以使用switch(因为它本质上是一组int值),这样比使用一组if…else…要明确。例如要判断currentLevel的值,可以写为:
switch (currentLevel)
{
case LevelSelect.Easy:
Debug.Log("Easy level");
break;
case LevelSelect.Normal:
//...
break;
// ...
}
枚举类型自动生成的ToString()方法会打印出枚举的字面值,例如:
Debug.Log("关卡难度为:" + currentLevel.ToString());
Debug.Log("关卡难度为:" + currentLevel); // 效果相同,隐式调用ToString
会打印出“关卡难度为:Easy”。用这个方法可以测试枚举值是否符合预期。
有时候需要提取枚举对应的int值,这时可以用(int)进行类型转换。例如上例中设置的四种关卡难度分别对应了四个关卡,我们希望直接用枚举值给出LoadScene函数需要的index参数,则可以:
// 已设置好4个关卡对应的index
SceneManager.LoadScene((int)currentLevel);
枚举的使用还有一些进阶的技巧。例如对于文字排版的描述,枚举值有AlignLeft(左对齐),AlignBottom(底部对齐),AlignHCenter(水平居中对齐),AlignVCenter(垂直居中对齐),AlignCenter(全部居中对齐)等等。这里有水平和垂直两个方向的信息,我们希望可以通过某种运算进行组合,例如使AlignHCenter和AlignVCenter等价于AlignCenter。这里会常用到“|”,即按位或运算符。只要枚举值的设计合理,就可以实现。例如在Qt中,Qt命名空间下的很多枚举值就是这么处理的:
注意水平和垂直方向的取值设计保证了不会出现如AlignLeft | AlignTop = AlignBottom这样的“撞车”问题。