Unity C#编程优化——枚举

简介: 考虑下面关于行星枚举的这个例子:public enum Planet {    MERCURY,    VENUS,    EARTH,    MARS,    JUPITER,    SATURN,    URANUS,    NEPTUNE,    PLUTO // Pluto is a planet!!!}起初,这样的定义还算好,直到需要产生一个行星的质量。

考虑下面关于行星枚举的这个例子:
public enum Planet {
    MERCURY,
    VENUS,
    EARTH,
    MARS,
    JUPITER,
    SATURN,
    URANUS,
    NEPTUNE,
    PLUTO // Pluto is a planet!!!
}
起初,这样的定义还算好,直到需要产生一个行星的质量。所以我们做这样的事情:
// Returns the mass of the planet in 10^24 kg
public float GetMass(Planet planet) {
    switch(planet) {
        case Planet.MERCURY:
            return 0.330;
        case Planet.VENUS:
            return 4.87f;
        case Planet.EARTH:
            return 5.97f;
        ...
        case Planet.PLUTO:
            return 0.0146f;
    }
}

行星直径又如何? 另一个switch语句? 密度怎么样? 重力? 逃跑速度? 只要想想你将要维护的switch语句的数量。 你可以争辩说,你可以使用一个Dictionary,但仍然笨重。 每个数据的Dictionary都要映射?没门。

有一个更好的方法,我会告诉你如何。 这可能已经是非Unity程序员的常识,但我想在我的博客中再次提出这个冗余的主题,对于那些可能不知道这一点的人来说,特别是初学者。 我也想保持简单。

基本上,你可以使用类作为枚举。 为什么用类? 这确实表现的更好 您可以存储任意数量的任意数据。 您甚至可以存储例程或功能。 你可以做很多事情。 唯一的要求是它是不可变的,这意味着类一个实例的状态在整个程序期间都不能改变。以下是Planet枚举用类表示的一个版本:
public class Planet {
       // The different values
       public static readonly Planet MERCURY = new Planet(0, 0.330f, 4879, 5427, 3.7f);
       public static readonly Planet VENUS = new Planet(1, 4.87f, 12104, 5243, 8.9f);
       public static readonly Planet EARTH = new Planet(2, 5.97f, 12756, 5514, 9.8f);
       public static readonly Planet MARS = new Planet(3, 0.642f, 6792, 3933, 3.7f);
       public static readonly Planet JUPITER = new Planet(4, 1898.0f, 142984, 1326, 23.1f);
       public static readonly Planet SATURN = new Planet(5, 568.0f, 120536, 687, 9.0f);
       public static readonly Planet URANUS = new Planet(6, 86.8f, 51118, 1271, 8.7f);
       public static readonly Planet NEPTUNE = new Planet(7, 102.0f, 49528, 1638, 11.0f);
       public static readonly Planet PLUTO = new Planet(8, 0.0146f, 2370, 2095, 0.7f);
       // Use readonly to maintain immutability
       private readonly int id;
       private readonly float mass; // in 10^24 kg
       private readonly int diameter; // in km
       private readonly int density; // in kg/m^3
       private readonly float gravity; // in m/s^2
       // We use a private constructor because this should not be instantiated
       // anywhere else.
       private Planet(int id, float mass, int diameter, int density, float gravity) {
           this.id = id;
           this.mass = mass;
           this.diameter = diameter;
           this.density = density;
           this.gravity = gravity;
       }
       public int Id {
           get {
               return id;
           }
       }
       public float Mass {
           get {
               return mass;
           }
       }
       public int Diameter {
           get {
               return diameter;
           }
       }
       public int Density {
           get {
               return density;
           }
       }
       public float Gravity {
           get {
               return gravity;
           }
       }
   }
为了保持不变性,所有成员变量应该是只读的。 一旦他们被分配,他们将不能再被改变。 这很重要,因为作为枚举,它的内部值不应该改变。 然后将每个枚举值实现为该类的静态只读实例。

这是怎么用的? 与正常枚举是一样的,如下使用:
// Use it like an enum
ship.TargetPlanet = Planet.NEPTUNE;
// Want to know the target planet's mass?
float mass = ship.TargetPlanet.Mass;
// Density?
int density = ship.TargetPlanet.Density;
我们已经消除了切换语句或字典来维护不同行星信息的需要。 想要一个新的行星状态? 只需添加一个新的成员变量并在实例化上指定它们。
如何从其他数据类型转换? 喜欢说从int id转换为Planet实例? 这很容易 通常我为这些转换添加了一个公共和静态方法。 例如:
public class Planet {
    // The different values
    public static readonly Planet MERCURY = new Planet(0, 0.330f, 4879, 5427, 3.7f);
    public static readonly Planet VENUS = new Planet(1, 4.87f, 12104, 5243, 8.9f);
    public static readonly Planet EARTH = new Planet(2, 5.97f, 12756, 5514, 9.8f);
    public static readonly Planet MARS = new Planet(3, 0.642f, 6792, 3933, 3.7f);
    public static readonly Planet JUPITER = new Planet(4, 1898.0f, 142984, 1326, 23.1f);
    public static readonly Planet SATURN = new Planet(5, 568.0f, 120536, 687, 9.0f);
    public static readonly Planet URANUS = new Planet(6, 86.8f, 51118, 1271, 8.7f);
    public static readonly Planet NEPTUNE = new Planet(7, 102.0f, 49528, 1638, 11.0f);
    public static readonly Planet PLUTO = new Planet(8, 0.0146f, 2370, 2095, 0.7f);
    // This can be used to loop through all planets
    public static Planet[] ALL = new Planet[] {
        MERCURY, VENUS, EARTH, MARS, JUPITER, SATURN, URANUS, NEPTUNE, PLUTO
    };
    // Converts the specified id to a Planet instance
    public static Planet Convert(int id) {
        for(int i = 0; i < ALL.Length; ++i) {
            if(ALL.Id == id) {
                return ALL;
            }
        }
        // return ALL[id] could also work here but what if a non sequential id is used?
        throw new Exception("Cannot convert {0} to a Planet.".FormatWith(id));
    }
    ...
}
// Usage
Planet planet = Planet.Convert(someIntPlanet);


想从字符串ID转换? 添加将保存此值的字符串成员变量。 而不是使用诸如ALL []的数组,您可以使用如下所示的Dictionary:
private static Dictionary<string, planet="" style="color: rgb(34, 34, 34); font-family: 微软雅黑; font-size: 15px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration-style: initial; text-decoration-color: initial;"> ALL = new Dictionary<string, planet="">() {
    { MERCURY.TextId, MERCURY },
    { VENUS.TextId, VENUS },
    { EARTH.TextId, EARTH },
    ...
    { PLUTO.TextId, PLUTO },
};
// Converts the specified string to a Planet instance
public static Planet Convert(string id) {
    return ALL[id];
}


您可以支持您喜欢的任何类型的转换。
还有更多的你可以做。 您现在可以添加功能。 你可以这样做:
Planet currentPlanet = Planet.VENUS;
currentPlanet.ApplyGravity(ship);
The coolest thing for me is you can specify different actions or behavior to the enum values. Something like this (It’s very contrived but you get the idea.):
public static readonly Planet EARTH = new Planet(2, 5.97f, 12756, 5514, 9.8f, delegate(Ship ship) {
    // Actions on land of ship
    ship.AddFood(1000);
    ship.RetireCrew();
    ship.RecruitNewCrew();
});
public static readonly Planet MARS = new Planet(3, 0.642f, 6792, 3933, 3.7f, delegate(Ship ship) {
    // Actions on land of ship
    ship.DeductFood(50);
    ship.Research();
    ship.Mine();
});


通过简单地将你的枚举变成一个类,你已经将它升级到更有组织的东西,而且更加功能强大。 您也可以使用反射和继承等先进功能,但大多数情况下,您不需要。

 更多unity2018的功能介绍请到paws3d学习中心查找。

相关文章
|
2月前
|
XML 前端开发 C#
C#编程实践:解析HTML文档并执行元素匹配
通过上述步骤,可以在C#中有效地解析HTML文档并执行元素匹配。HtmlAgilityPack提供了一个强大而灵活的工具集,可以处理各种HTML解析任务。
145 19
|
6月前
|
存储 监控 算法
解析公司屏幕监控软件中 C# 字典算法的数据管理效能与优化策略
数字化办公的时代背景下,企业为维护信息安全并提升管理效能,公司屏幕监控软件的应用日益普及。此软件犹如企业网络的 “数字卫士”,持续记录员工电脑屏幕的操作动态。然而,伴随数据量的持续增长,如何高效管理这些监控数据成为关键议题。C# 中的字典(Dictionary)数据结构,以其独特的键值对存储模式和高效的操作性能,为公司屏幕监控软件的数据管理提供了有力支持。下文将深入探究其原理与应用。
130 4
|
3月前
|
监控 算法 C#
C#与Halcon联合编程实现鼠标控制图像缩放、拖动及ROI绘制
C#与Halcon联合编程实现鼠标控制图像缩放、拖动及ROI绘制
470 0
|
C# 开发者
C# 一分钟浅谈:Code Contracts 与契约编程
【10月更文挑战第26天】本文介绍了 C# 中的 Code Contracts,这是一个强大的工具,用于通过契约编程增强代码的健壮性和可维护性。文章从基本概念入手,详细讲解了前置条件、后置条件和对象不变量的使用方法,并通过具体代码示例进行了说明。同时,文章还探讨了常见的问题和易错点,如忘记启用静态检查、过度依赖契约和性能影响,并提供了相应的解决建议。希望读者能通过本文更好地理解和应用 Code Contracts。
234 3
|
5月前
|
机器学习/深度学习 监控 算法
局域网行为监控软件 C# 多线程数据包捕获算法:基于 KMP 模式匹配的内容分析优化方案探索
本文探讨了一种结合KMP算法的多线程数据包捕获与分析方案,用于局域网行为监控。通过C#实现,该系统可高效检测敏感内容、管理URL访问、分析协议及审计日志。实验表明,相较于传统算法,KMP在处理大规模网络流量时效率显著提升。未来可在算法优化、多模式匹配及机器学习等领域进一步研究。
146 0
|
11月前
|
缓存 API C#
C# 一分钟浅谈:GraphQL 优化与性能提升
本文介绍了 GraphQL API 的常见性能问题及优化方法,包括解决 N+1 查询问题、避免过度取数据、合理使用缓存及优化解析器性能,提供了 C# 实现示例。
207 33
|
11月前
|
存储 安全 编译器
学懂C#编程:属性(Property)的概念定义及使用详解
通过深入理解和使用C#的属性,可以编写更清晰、简洁和高效的代码,为开发高质量的应用程序奠定基础。
755 12
|
9月前
|
缓存 图形学
Unity C#for和foreach效率比较
该代码对比了三种遍历 `List&lt;int&gt;` 的方式的性能:使用缓存 `Count` 的 `for` 循环、每次访问 `list.Count` 的 `for` 循环以及 `foreach` 循环。通过 `Stopwatch` 测量每次遍历 300 万个元素所花费的时间,并输出结果。测试可在 Unity 环境中运行,按下空格键触发。结果显示,缓存 `Count` 的 `for` 循环性能最优,`foreach` 次之,而每次都访问 `list.Count` 的 `for` 循环最慢。
|
12月前
|
设计模式 C# 图形学
Unity 游戏引擎 C# 编程:一分钟浅谈
本文介绍了在 Unity 游戏开发中使用 C# 的基础知识和常见问题。从 `MonoBehavior` 类的基础用法,到变量和属性的管理,再到空引用异常、资源管理和性能优化等常见问题的解决方法。文章还探讨了单例模式、事件系统和数据持久化等高级话题,旨在帮助开发者避免常见错误,提升游戏开发效率。
459 4
|
安全 程序员 编译器
C#一分钟浅谈:泛型编程基础
在现代软件开发中,泛型编程是一项关键技能,它使开发者能够编写类型安全且可重用的代码。C# 自 2.0 版本起支持泛型编程,本文将从基础概念入手,逐步深入探讨 C# 中的泛型,并通过具体实例帮助理解常见问题及其解决方法。泛型通过类型参数替代具体类型,提高了代码复用性和类型安全性,减少了运行时性能开销。文章详细介绍了如何定义泛型类和方法,并讨论了常见的易错点及解决方案,帮助读者更好地掌握这一技术。
219 11