我正在尝试优化实体组件系统游戏引擎(ECS)。

版本A

当前,将通过3个步骤创建一个船实体。

  • SystemShip请求ECS创建新的空白实体
  • SystemShip要求ECS附加ComShip
  • SystemShip请求SystemHP附加任何组件 SystemHP 希望使某个实体具有HP功能。

这是1个实体的内存布局。
(我知道有几种方法,但是我决定选择这种布局。)

在此处输入图片说明

它工作正常,这是存根(可运行):-

class Entity{};
class ECS{
    public: static Entity createEntity(){
        return Entity();
    }
    public: template<class C> static void attach(Entity e){
        //some logic that extend memory used for "e" 
        //   also placement new (...) C();
        return;
    }
};
class ComHP{};
class SystemHP{
    public: static void addHPFeature(Entity e){
        ECS::attach<ComHP>(e);
        // set some value to the ComHP instance
        return;
    }
};
class ComShip{};
class SystemShip{
    public: static Entity createShip(){
        Entity entity=ECS::createEntity();
        ECS::attach<ComShip>(entity);
        SystemHP::addHPFeature(entity);
        return entity;
    }
};
int main(){
    Entity e=SystemShip::createShip();
}

版本B

后来我发现上述方法对内存管理不是很友好。

如果ECS在实体创建时知道它需要的每种类型的组件,那么进行优化就容易得多,而且如果我在程序开始时 (例如使用模板)知道它,则更好。

使用以下解决方案,它可以保留正确大小的内存。 (标记为##HAPPY##
这是一个设计存根:-

class Entity{};
class ECS{
    public: template<class ...C> static Entity createEntity2(){
        //##HAPPY##
        //some logic that extend memory used for "e" 
        //   also placement new (...) ComShip() and ComHP();
        return Entity();
    }
};
class ComHP{};
class SystemHP{
    public: static void addHPFeature(Entity e){
        // set some value to the ComHP instance
        return;
    }
};
class ComShip{};
class SystemShip{
    public: static Entity createShip(){
        Entity entity=ECS::createEntity2<ComShip,ComHP>();
        SystemHP::addHPFeature(entity);
        return entity;
    }
};
int main(){
    Entity e=SystemShip::createShip();
}

问题

虽然有效,但是版本B有3个缺点:-

1

现在, SystemShip必须识别SystemHP需要哪种类型的组件。

它以某种方式破坏了封装,并且很难维护。

如果SystemHP需要更多组件来实现HP功能,则需要重构SystemShip和其他调用SystemHP::addHPFeature()

第2

版本B的代码以某种方式重复了:-

 1. Entity entity=ECS::createEntity2<ComShip,ComHP>(); //ComHP <-- forget
 2. SystemHP::addHPFeature(entity);                    //HP again

比较版本A:-

 SystemHP::addHPFeature(entity);                       //one line

这有点容易出错:创建实体时,我可能会忘记添加ComHP

第3

SystemShip需要的完整定义ComHP
可以通过使用std :: function或其系列来缓解它,但是会损失函数指针(或v表)的开销。

如何减轻版本B的弊端?

编辑:
我觉得部分解决方案是让SystemHP具有pack type-def。
可能是SystemHP::allTypesRequired ,我可以像createEntity3<ComShip,SystemHP::type_allTypesRequired>()一样使用它。
我必须找到一种将其压缩并解压缩回组件类型列表( {ComHP} )的方法。

  ask by cppBeginner translate from so

本文未有回复,本站智能推荐:

1回复

如何在 ECS 模型中组织实体?

我有一个渲染系统,它遍历所有 MeshDrawData 组件并批量绘制它们。 我的 ECS 实现只允许每个实体使用一种类型的组件。 现在我想代表“玩家”乒乓球拍。 我的 OOP 心态是这样说的: 这工作正常,但假设现在我也想渲染一条线。 如果我这样做: 在这里你可以看到问题.. 我为实体
2回复

避免与实体组件系统中与1:N关系相关的缓存未命中

如何避免与实体组件系统(ECS)中的1:N( pirateship - cannon )关系相关的缓存丢失? 例如, PirateShip可以拥有1至100门cannons 。 (1:N) 每门cannon都可以在任何时间自由地脱离pirateship 。 由于某些原因 , P
2回复

访问`std :: vector`的保留但不是按大小分配的内存作为原始内存是否安全?

如果要分配一个内存块而不将其初始化为零,执行以下操作是否安全? 如果不是,是否有比malloc和free更新的工具来完成这项工作?
3回复

如何在不使用C ++中使用新运算符的情况下在堆中创建对象?

C ++中的new运算符用于在堆内存中创建新对象。 我不知道是否在不使用new运算符的情况下如何在堆内存中创建对象。 有可能吗?如何? 还可以有人建议我使用C ++中的new opeartor在堆栈中创建对象吗?
1回复

组件实体系统实体特定数据

我已经用JavaScript编写组件实体系统已有一段时间了,但我一直回到根本问题上。 您如何处理特定于实体的功能(即单个实例或单个类型)的功能? 这是当前情况: 我采用的结构化方式是,当一个项目实体由另一个实体存储在库存中时,它不会被破坏,只是剥离了其大部分组件。 这样一来,
2回复

实体组件系统框架的最佳数据结构

我已经阅读了很多有关实体框架的知识,现在我想在我的游戏中实现它。 实体框架基于使游戏实体成为简单的组件容器的基础,其中组件包含实体的某个特征(以及描述该特征的所有变量/访问器)。 然后,通过创建系统将游戏逻辑模块化。 每个系统都实现并运行游戏逻辑的某个方面(例如,碰撞,渲染,动画)。 每
1回复

关于纯ECS(实体组件系统)和更新系统的问题

我已经写了一个 ECS,但我对更新阶段有一些疑问。 (在系统中)我已经阅读了很多文章,但没有找到对此类问题的引用。 为了从 ECS 中受益(例如缓存友好),它们有以下要求: 实体必须只是一个 ID。 组件只能是纯数据(没有逻辑的结构)。 系统包含逻辑并更新组件。 系统之间没有交
2回复

ECS序列化

我目前正在为游戏引擎开发ECS系统,偶然发现了序列化问题。 我在ECS实施中用于组件存储的数据结构是一个预先构造的组件池,这些组件被回收。 因此,添加实体与为预先构造的组件分配值一样简单。 该系统旨在利用组件标识符而不是类型,这就是问题所在。 序列化和反序列化时,组件将被视为BaseCo