实体 - 组件系统:害怕丢失类型&可读性

时间:2017-03-06 13:19:58

标签: visual-studio c++11 architecture entity components

我有一个实体组件系统。

组件:包含数据的类,但没有复杂的功能
实体:整数+组件列表(< =每个实体每个类型1个实例)
系统:具有最少数据的许多功能,执行复杂的游戏逻辑

这是一个示例。子弹实体pewpew被爆炸,因此它将设置为不可见(#2): -

class Component_Projectile : public ComponentBase{
    public: GraphicObject* graphicObject=nullptr;     //#1
    public: Entity whoCreateMe=nullptr;
    public: Entity targetEnemy=nullptr;
    //.... other fields ....
};
class System_Projectile : public SystemBase {
    public: void explodeDamage(Entity pewpew){ //called every time-step
        Pointer<Component_Projectile> comPro=pewpew;
        comPro->graphicObject->setVisible(false);     //#2
        //.... generate some cool particles, damage surrounded object, etc
    }
    //.... other functions ....
};

一切正常。

新版本

半年后,我意识到我的架构看起来不一致。

  • 我使用game-logic object缓存所有Entity
  • 但是通过直接指针缓存Physic ObjectGraphic Object。 (例如#1

我有一个疯狂的想法:
Physic ObjectGraphic Object也应为game-logic object
它们应封装在Entity

现在代码将是(更改标有#1#2): -

class Component_Projectile : public ComponentBase{
    public: Entity graphicObject=nullptr;                         //#1
    public: Entity whoCreateMe=nullptr;
    public: Entity targetEnemy=nullptr;
    //.... other fields ....
};
class System_Projectile : public SystemBase {
    public: void explodeDamage(Entity pewpew){ //called every time-step
        Pointer<Component_Projectile> comPro=pewpew;
        system_graphic->setVisible(comPro->graphicObject,false);  //#2
        //.... generate some cool particles, damage surrounded object, etc
    }
    //.... other functions ....
};

在玩了一个星期之后,我可以总结这种方法的优点/缺点如下: -

优势

1。大大减少游戏逻辑VS图形引擎/物理引擎之间的耦合

所有特定于图形的功能现在都封装在1-3个系统中 没有其他游戏系统(例如System_Projectile)参考硬编码类型,例如GraphicObject

2。显着提高设计灵活性

旧香草图形对象不再只是一个图形对象了!

我可以将其更改为其他内容,尤其是添加对于物理/图形引擎完全疯狂/过于具体的特殊功能,例如:

  • 彩虹闪烁图片
  • 奇怪的引力,磁铁
  • 在同一个实体中交换/输出许多物理对象类型(不确定)

第3。缩短编译时间
它偶然成了一个流行语成语 例如,System_Projectile不再需要#include "GraphicObject.h"

缺点

1。我必须封装许多图形/物理对象的功能。
例如,

system_graphic->setVisible(comPro->graphicObject,false);

实现为

public: void setVisible(Entity entity,bool visible){
    entity.getComponent<Graphic_Component>()->underlying->setVisible(visible);
}

这很乏味,但不是很辛苦 它可以通过<...>得到部分缓解。

2。性能(仅)稍差一点。
需要一些额外的间接。

第3。代码可读性较差。
新版本难以阅读。

comPro->graphicObject->setVisible(false);                //old version
system_graphic->setVisible(comPro->graphicObject,false); //new version

4。丢失类型+ Ctrl+space不太可用
在旧版本中,我可以在此代码中轻松ctrl+space: -

comPro->graphicObject-> (ctrl+space)

现在更难了。我必须考虑我想打电话给哪个系统。

system_(ctrl+space)graphic->(ctrl+space)setVisible

问题

在大多数代码位置,优势克服了缺点,所以我决定使用新版本。

如何减轻缺点,特别是3号和4号? 设计模式? C ++魔术?
我可能以错误的方式使用实体组件系统。 (?)

0 个答案:

没有答案