C++成员变量更改侦听器(100多个类)

ioa*_*nb7 5 c++ oop mmo

我正在尝试为MMO游戏制作一个架构,我无法弄清楚如何在游戏对象中存储尽可能多的变量而没有很多调用在我更新它们的同时在线上发送它们.

我现在拥有的是:

Game::ChangePosition(Vector3 newPos) {
    gameobject.ChangePosition(newPos);
    SendOnWireNEWPOSITION(gameobject.id, newPos);
}
Run Code Online (Sandbox Code Playgroud)

它使代码变得垃圾,难以维护,理解和扩展.想想一个冠军的例子:

GameObject Champion示例

我必须为每个变量创建很多函数.这只是这个冠军的概括,我可能每个冠军类型/"类"都有1-2个其他成员变量.

如果我能从.NET或类似的东西中获得OnPropertyChange,那将是完美的.我想要的架构可以很好地工作,如果我有类似的东西:

对于HP:当我更新它时,自动呼叫 SendFloatOnWire("HP", hp);

对于位置:当我更新它时,自动调用 SendVector3OnWire("Position", Position)

对于名称:当我更新它时,自动调用 SendSOnWire("Name", Name);

什么是完全相同SendFloatOnWire,SendVector3OnWire,SendSOnWire?在char缓冲区中序列化这些类型的函数.

或方法2(优先),但可能很昂贵

更新Hp,正常定位,然后每个网络线程勾选扫描服务器上所有已更改变量的GameObject实例并发送它们.

如何在高规模的游戏服务器上实现,我有哪些选择?这类案件有用吗?

宏会变得有用吗?我想我已经开发了类似的一些源代码,我认为它使用了宏.

先感谢您.

编辑:我想我找到了一个解决方案,但我不知道它实际上有多强大.我打算去看看,然后看看我的立场.https://developer.valvesoftware.com/wiki/Networking_Entities

ioa*_*nb7 0

我得出的总体结论是:更新职位后再打一次电话,也不错。这是一行代码更长,但对于不同的动机来说更好:

  1. 这是明确的。你清楚地知道发生了什么。
  2. 您不会通过进行各种修改来使其运行而减慢代码速度。
  3. 您不使用额外的内存。

我尝试过的方法:

  1. 按照 @Christophe 的建议,为每种类型提供地图。它的主要缺点是不容易出错。您可能已经在同一个映射中声明了 HP 和 Hp,这可能会增加另一层问题和挫折,例如为每种类型声明映射,然后在每个变量前面加上映射名称。
  2. 使用类似于Valve引擎的东西:它为您想要的每个网络变量创建了一个单独的类。然后,它使用模板来包装您声明的基本类型(int、float、bool)以及该模板的扩展运算符。它使用了太多的内存和对基本功能的额外调用。
  3. 使用数据映射器为构造函数中的每个变量添加指针,然后使用偏移量发送它们。当我意识到代码开始变得混乱且难以维护时,我过早地离开了该项目。
  4. 使用每次发生更改时手动发送的结构。使用protobuf可以轻松完成此操作。扩展结构也很容易。
  5. 每个时钟周期,都会生成一个包含类数据的新结构并发送它。这可以使非常重要的内容始终保持最新,但会占用大量带宽。
  6. 在 boost 的帮助下使用反射。这不是一个很好的解决方案。

毕竟,我混合使用了 4 和 5。现在我正在我的游戏中实现它。protobuf 的一大优势是能够从 .proto 文件生成结构,同时还为您提供结构的序列化。它的速度快得惊人。

对于子类中出现的那些特殊命名变量,我制作了另一个结构体。或者,在 protobuf 的帮助下,我可以拥有一组简单的属性ENUM_KEY_BYTE VALUE:其中ENUM_KEY_BYTE是一个引用 aenum到诸如IS_FLYINGIS_UPIS_POISONED和 等属性的字节,并且VALUE是 a string

我从中学到的最重要的事情是尽可能多的序列化。两端使用更多的 CPU 比拥有更多的输入和输出要好。

如果有人有任何疑问,请评论,我会尽力帮助您。

ioanb7