我正在尝试优化实体组件系统游戏引擎(ECS)。
目前,通过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();
}
我后来发现上述方法对内存管理不太友好。
如果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有三个缺点: -
现在,SystemShip
必须识别SystemHP
想要的组件类型。
它以某种方式打破了封装,并且维护起来相当困难。
如果SystemHP
需要更多组件来实施HP
功能,我需要重构SystemShip
以及其他调用SystemHP::addHPFeature()
的地方。
版本B的代码以某种方式重复: -
1. Entity entity=ECS::createEntity2<ComShip,ComHP>(); //ComHP <-- forget
2. SystemHP::addHPFeature(entity); //HP again
比较版本A: -
SystemHP::addHPFeature(entity); //one line
这有点容易出错:我可能忘记在创建实体时添加ComHP
。
SystemShip
要求ComHP
的完整定义
它可以通过使用std :: function或其族来缓解,但是会受到函数指针(或v表)的影响。
如何减轻B版的缺点?
修改
我认为部分解决方案是让SystemHP
具有包类型def
可能SystemHP::allTypesRequired
我可以像createEntity3<ComShip,SystemHP::type_allTypesRequired>()
一样使用它
我必须找到一种方法来压缩它并将其解压缩回组件类型列表({ComHP}
)。