C# 抛开OO设计模式,在战略游戏中获得更好的性能?

C# 抛开OO设计模式,在战略游戏中获得更好的性能?,c#,performance,caching,C#,Performance,Caching,假设由于某些原因和限制,我们希望有效地编程。 我们应该把OOP放在一边吗? 让我们用一个例子来说明 public class CPlayer{ Vector3 m_position; Quaternion m_rotation; // other fields } public class CPlayerController{ CPlayer[] players; public CPlayerController(int _count){ players

假设由于某些原因和限制,我们希望有效地编程。 我们应该把OOP放在一边吗? 让我们用一个例子来说明

public class CPlayer{
   Vector3 m_position;
   Quaternion m_rotation;
   // other fields
}
public class CPlayerController{
   CPlayer[] players;
   public CPlayerController(int _count){
      players=new CPlayer[_count];
   }
   public void ComputeClosestPlayer(CPlayer _player){
      for(int i=0;i<players.Length;i++){
           // find the closest player to _player
      }
   }
}
所以现在,当我们调用函数时,只有位置(每个位置12个字节)缓存在缓存中,而在前面的方法中,我们必须缓存占用更多内存的对象


最后,我不知道这是一种标准的方法,或者你避免将一些字段从类中分离出来以获得更好的性能,并分享你的方法以在策略游戏中获得最大的性能,因为你有很多物品和士兵

在结构还是类之间做出决定可能非常棘手。结构成为值类型,而类成为引用类型。值类型由值传递,这意味着结构的内容被复制到数组、函数参数等。。。引用类型是通过引用传递的,这意味着只传递它们的引用。另一个性能问题可能来自频繁装箱和取消装箱的值类型

我可能解释得不好,幸运的是MSDN有一个很好的指南

我想在这里复制的一件事是:

考虑定义结构而不是类,如果 类型较小,通常寿命较短,或者通常嵌入 在其他对象中

X避免定义结构,除非该类型具有所有 以下特点:

  • 它在逻辑上表示单个值,类似于基本类型(
    int
    double
    ,等等)

  • 它的实例大小小于16字节

  • 它是不变的

  • 它不必经常装箱

在所有其他情况下,您应该将类型定义为类

抛开面向对象的设计模式,在战略领域实现更好的性能 游戏

我倾向于在中央体系结构中将面向对象编程(OOP)放在visual FX的一边,特别是使用实体组件系统,如:

。。。其中蓝色的组件只是数据(
structs
,没有自己的功能)。如果组件内部有任何功能,它是纯数据结构功能(如您在代码> STD中找到的函数::C++中的向量< /代码>或<代码> ARLayList< /C> > C)。

它确实让高效的事情更容易完成,但对我来说,主要的好处不是效率。这就是灵活性和可维护性。当我需要全新的行为时,我可以只对系统进行一个小的局部修改,或者添加一个新组件,或者在广泛的依赖关系流向数据而不是抽象时添加一个新系统。自从我接受这种方法以来,面对层叠式设计变更的需求已经成为过去

“无中心设计”

每一个新的设计理念,无论多么疯狂,都很容易扩展并添加到系统中,而不会破坏任何中心设计,因为除了ECS数据库本身之外,根本没有中心抽象设计(或包含功能的设计)。除了对ECS数据库和每个系统中的少数组件(原始数据)的依赖之外,系统是uber解耦的

它使每个系统都很容易推理,从线程安全到何时何地发生的副作用。每个系统都执行一个非常明确的角色,该角色非常直接地映射到业务需求。当您将此用于中等大小和微小大小对象之间的通信/交互时,更难对设计和责任进行推理:

。。。上面的图不是依赖关系图。就耦合而言,每个对象之间可能都有一个抽象,以这种方式将它们解耦(例如:建模对象取决于
IMesh
,而不是具体的网格),但它们仍然相互通信,所有这些交互和交流都会使我们很难对正在发生的事情进行推理,也很难想出最有效的循环代码

同时,第一个系统让每个独立的系统以扁平管道方式处理来自中央数据库的数据,这使得我们很容易弄清楚发生了什么,并非常高效地实现循环关键执行路径。它还使您可以坐下来在一个系统上工作,而不必知道其他系统正在做什么:实现物理系统所需做的就是从数据库中读取运动组件之类的内容,并正确转换数据。除了一些组件类型以及如何从ECS“数据库”中获取它们之外,您不需要了解太多的物理系统的实现和维护

这也使得团队合作变得更容易,同时也雇佣了新的开发人员,他们可以快速跟上进度,而不需要花2年的时间来教他们整个系统中的中心抽象是如何工作的,这样他们就可以完成他们的工作。他们可以在几周内开始做一些大胆的事情,比如在系统中引入一个全新的物理引擎或渲染引擎

效率

如果我们将类转换为结构,我们可以利用 播放器阵列在缓存中,并获得更好的性能

这只是在粒度级别上,对象开始妨碍性能。例如,如果您尝试使用抽象的
像素
对象或封装和隐藏其数据的
IPixel
接口来表示图像的单个像素,那么即使不考虑动态调度的成本,它也很容易成为性能障碍。这样的颗粒对象只会迫使您以一个像素一次的颗粒级别工作
public struct CPlayerController{
   CPlayer[] players;
   public CPlayerController(int _count){
      players=new CPlayer[_count];
   }
   public void ComputeClosestPlayer(CPlayer _player){
      for(int i=0;i<players.Length;i++){
           // find the closest player to _player
      }
   }
}
public Vector3[] m_positions;
public Vector3[] m_positions;
xyzxyzxyzxyz...
xxxxxxxx...
yyyyyyyy...
zzzzzzzz...
float[] m_x;
float[] m_y;
float[] m_z;