【问题标题】:How to avoid virtual functions in C when designing an Entity System设计实体系统时如何避免 C 中的虚函数
【发布时间】:2019-04-15 00:16:03
【问题描述】:

我想为我的游戏设计一个实体系统,只使用 C 和一小部分 C++。很多人使用继承来做到这一点,但我偶然发现标记的联合并了解到您可以通过这种方式获得类似的结果,因为虚拟函数对于游戏来说很慢(所以我从 Casey Mouratori 和 Jon Blow 那里听说过,两个游戏开发者,我从中汲取了很多灵感)。

struct Unit {
   int type;
   int hp;
   union {
      struct {
        int kingID; 
      } soldier_data;

      struct {
        string name;
      } king_data;
   };
}

Jon Blow 使用尚未发布的新语言 Jai 中的一些特性来避免使用虚函数,所以上面的示例是我唯一的想法。

例如,我可以只编写一个更新函数并使用类型来区分实体。这将是一个非常大的函数,但是,我们避免使用虚函数。

事情是我的游戏包含让我们说士兵和树木。树是静态的,几乎什么都不做,所以我会为树实体编写另一个更轻的结构,以节省一些内存,并使用联合来存储不同类型的树:

struct TreeEntity {    
      Texture* texture;    
      union {
        struct {
           int height;
        } pineTree_data;
        struct {
           string name;
        } coconutTree_data;
   }
}

我面临的问题是如果士兵和树木都是可点击? 如果我使用了继承,我会简单地拥有一个函数 Entity* selectEntity(),然后检查实例类型,但是用我的方法我有点迷路了。

我的方法不好吗?我应该坚持使用虚函数还是有办法处理这个问题?

【问题讨论】:

  • “虚拟函数对游戏来说很慢” 这可能是断章取义的。虚函数本质上是函数指针,而且非常快与实现相同功能所需的替代方案相比,它们通常是性能最高的选项
  • 一小部分 C++:所以你用 C++ 编译器编译?如果适用,请澄清并添加 C++ 标签。
  • 您使用枚举 + 数据创建“变体”联合的方法将引入额外的分支,这些分支不在使用函数指针进行继承的替代方案中。因为每次访问这个“变体”时,都需要检查“我是谁?”。很可能,这是一个坏主意。但是没有足够的背景来说明,这个问题太宽泛了。
  • 使用 std::visit 运行变体只是将您的虚函数调用替换为索引函数指针表查找。在汇编中,这应该导致多一条指令。如果在编译期间完全完成跳转表生成,这只是最好的情况。做所有这些手工制作只对自学有用。 @user694733:使用虚函数不仅会导致使用 vtable 指针跳转,而且在某些情况下也无法进行优化。因此,在高架海岸上不仅有呼叫本身!
  • @Klaus 是的,当然。我只是说对于许多问题,即使在游戏中,它们仍然足够快。许多初学者可能会陷入设计过于复杂和无效的解决方法的陷阱。

标签: c c++11 virtual-functions game-development entity-system


【解决方案1】:

您问如何创建一个通用的Entity* selectEntity() 函数,该函数可以返回 Unit* 或 Tree*(或者可能是其他东西)。

你可以通过返回一个基类指针来做到这一点。 Unit 和 Tree 继承自 Entity,Entity 可以包含一个小的枚举,如:

enum class EntityType : uint8_t {
    Unit, Tree, // ...
};

如果您不想使用继承,则可以在每种类型的实体中只使用成员变量的公共初始子序列,如下所示:

struct Unit {
    EntityType type;
    // ...
};

这在内存布局方面相当于继承版本,您可以从selectEntity() 返回一个EntityType*,它实际上将指向一个单元或树的第一个成员。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-07-21
    • 1970-01-01
    • 2011-06-15
    • 2014-04-03
    • 2014-07-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多