zoukankan      html  css  js  c++  java
  • Unity中的枚举和标志

    译林军 宿学龙|2014-04-10 08:56|9007次浏览|Unity(377)0

    枚举和标志

    今天的主题是枚举,它是C#语言中的一个很有帮助的工具,可以增强代码的清晰度以及准确性。

    枚举一系列值

    C#中最经常使用枚举的地方就是用来定义一系列可能值的时候。例如在制作一个角色类游戏中,角色有多个不同的状态效果。可以用一些基本的方式来定义玩家可能的状态效果:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    using UnityEngine;
      
    public class Player : MonoBehaviour
    {
        public string status;
      
        void Update()
        {
            if (status == "Poison")
            {
                //Apply poison effect
            }
            else if (status == "Slow")
            {
                //Apply slow effect
            }
            else if (status == "Mute")
            {
                //Apply mute effect
            }
        }
    }

    此处我们用一个简单的if-else检测来查看应用的是哪个状态效果,哪个运行良好。但是如果你想应用一个状态效果,但是突然写成这样:

    1
    2
    //Oops, I spelled "Poison" wrong!
    status = "Pioson";

    突然,就不会有什么状态效果了。我们会利用if-else栈检测来查看我们的变量是否被设置成一个非法值,但是如果使用枚举,则是一种更好的方式:

    定义一个枚举

    这次我们使用一个枚举来编写我们的状态效果:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    using UnityEngine;
      
    public class Player : MonoBehaviour
    {
        //This is the "set" of all possible status effects
        public enum StatusEffect
        {
            None,
            Poison,
            Slow,
            Mute
        }
      
        //Now we can make a variable using that set as its type!
        public StatusEffect status;
      
        void Update()
        {
            if (status == StatusEffect.Poison)
            {
                //Apply poison effect
            }
            else if (status == StatusEffect.Slow)
            {
                //Apply slow effect
            }
            else if (status == StatusEffect.Mute)
            {
                //Apply mute effect
            }
        }
    }

    这里我们定义了一个叫StatusEffect的枚举,通过给状态赋值,我们强制编译器只等于StatusEffect中的一个值,如果还像之前赋值:

    1
    2
    //This type doesn't even exist, ERROR TIME!
    status = StatusEffect.Pioson;

    游戏就不可能运行,编辑器会抛出一个错误,告诉你正在使用一个非法的枚举值,并指出你需要修复的确切的代码行。

    在上述代码中,我没有制定状态的默认值,通常来说,一个枚举都是指定集合中的第一个值作为默认值的,因此在此例中,我已经说过,StatusEffect变量的任意默认值都是StatusEffect.None。

    如果你发现Unity中有专门为UI自定义的枚举,那就更好了,当我打开Player组件的查看器时,看看发生什么了。

    enum_dropdown

    一个干净整洁的下拉菜单用来选择定义的类型!

    枚举位标志

    StatusEffect枚举,如下:

    1
    2
    3
    4
    5
    6
    7
    8
    [System.Flags]
    public enum StatusEffect
    {
        None    = 1,
        Poison    = 2,
        Slow    = 4,
        Mute    = 8
    }

    通过如此,我们告知编译器将此枚举看做是位标记,表示每个不同的枚举值代表一个不同的位。这意味着我们必须通过给它们用2的幂来赋值,以此告知每个枚举值。另一种就是通过获取两个值的幂,然后通过移位来实现:

    1
    2
    3
    4
    5
    6
    7
    8
    [System.Flags]
    public enum StatusEffect
    {
        None   = 1 << 0, // 1
        Poison = 1 << 1, // 2
        Slow   = 1 << 2, // 4
        Mute   = 1 << 3  // 8
    }

    现在可以通过平常的位操作来控制这些枚举域了。如果你对位操作不熟悉,我会简单讲解下如何使用。

    枚举标志和位操作符

    现在我们的枚举值是通过System.Flags标记的,我们可以像之前一样,如下来做:

    1
    2
    //Character is poisoned!
    status = StatusEffect.Poison;

    但如果玩家中毒或者行动缓慢怎么办?我们可以使用或|操作符来将多个状态值合并一起:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    //Now we are poisoned *and* slowed!
    status = StatusEffect.Poison | StatusEffect.Slow;
      
    //We could also do this:
    //First we are poisoned, like so
    status = StatusEffect.Poison;
      
    //Then we become *also* slowed later
    status |= StatusEffect.Slow;

    如果我们想移除一个状态效果,我们可以使用&操作符和取反~。

    1
    2
    3
    4
    5
    //First, we are poisoned and muted
    status = StatusEffect.Poison | StatusEffect.Mute;
      
    //But now we want to remove just the poison, and leave him mute!
    status &= ~StatusEffect.Poison;

    最后如果我们检测发现如果一个玩家在if语句中,我们可以使用&操作符来查看一个特定的位值:

    1
    2
    3
    4
    5
    //Let's check if we are poisoned:
    if ((status & StatusEffect.Poison) == StatusEffect.Poison)
    {
        //Yep, definitely poisoned!
    }

    扩展阅读

    我不想此文全讲解位标志和位操作,因此我只是简要解释了下。但是如果你不了解位操作,我强烈建议你弄懂它们并制定如何使用。

    我个人喜欢维基百科的这个网页:

    http://en.wikipedia.org/wiki/Bitwise_operation

    同时,System.Flags标记的枚举不会直接在Unity的查看其中正确显示,它们不会让你选择设置某个标记的,之后以非标记的枚举类型显示。但庆幸的是,你可以自己写一个自定义的属性着色器来解决,之后我会在此文追加的!

    https://docs.unity3d.com/Documentation/ScriptReference/PropertyDrawer.html

    快乐编码!

    原文链接:Enums and Flags

  • 相关阅读:
    4.8 C++ typeid操作符
    4.7 C++ dynamic_cast操作符
    tomcat中class和jar的加载顺序(转)
    java Files类和Paths类的用法 (转)
    搭建DUBBO项目解决DUBBO.XML标签报错的问题(转载)
    Maven异常:Could not find artifact
    在docker宿主机上查找指定容器内运行的所有进程的PID
    jmap、jstack、jps无法连接jvm解决办法
    linux中如何查看某一进程的启动时间
    Eureka与ZooKeeper 的比较(转)
  • 原文地址:https://www.cnblogs.com/forlove/p/3785257.html
Copyright © 2011-2022 走看看