减少实体组件系统中的鸭子打字劣势

Posted

技术标签:

【中文标题】减少实体组件系统中的鸭子打字劣势【英文标题】:reduce Duck-typing disadvantage in entity-component-system 【发布时间】:2017-10-24 04:15:04 【问题描述】:

如何减少实体组件系统中的Duck-typing现象?

示例

这是一个coliru demo

我的 ECS 中有 2 个系统:-

System_Projectile :管理所有弹丸和子弹方面。System_Physic :管理物理组件。

有 2 种组件类型:Com_ProjectilePhysics

有时,我发现在某个组件中缓存指向另一个实体的指针是件好事:-

class Com_Projectile : public Component
    public:
    Entity* physic;
    Entity* physicSecondary; //just to show that it is possible to have >1 physic
;

如果我想改变Com_Projectile的位置,我会打电话给manage(Com_Projectile::physic)

class System_Projectile
    public: static void manage(Entity* projectile)
        Com_Projectile* comP = getComponent<Com_Projectile>(projectile);
        //suffer duck-typing at "comP->physic"
        System_Physic::setVelocity(comP->physic,Vec3(1,0,0));
    
;

问题

基于上述sn -p的真实程序运行正常。 然而,在编码时,Com_Projectile::physic 遭受鸭式打字。

我没有得到关于 physic 类型的 C++ 语义线索。 (变量名和注释除外)

因此,我必须意识到。 Coder 对类型的误解只会在运行时被发现。 但在实践中,这种错误很少发生。

我必须记住可以做我想做的事情的系统名称 (System_Physic::), 然后回忆函数的名称(在这种情况下为System_Physic::setVelocity())。

总之,我的大脑有很多间接

在我过去,当我使用大量(深度)继承时,它会容易得多,就像这样:-

    physic->setVelocity(Vec3(1,0,0));

我真的很怀念列出所有与物理相关的功能的可爱内容助手。

问题

如何减少 ECS 系统某些部分的鸭式打字? 更具体地说,再次启用可爱内容辅助的设计模式是什么?

我目前的解决方法

Com_Projectile缓存Physic* physic而不是Entity*:-

class Com_Projectile
    public: Physics* physic; //edited from "Entity* physic"
;

缺点:-

它会促进不需要的 (?) 耦合。 我必须在Com_Projectile.h 内转发声明Physics。 我必须将复杂功能(例如setVelocity())从系统(例如Sys_Physic::)移动到组件(例如Physics::)。 总的来说,我正在打破实体-组件-系统宗教 -> 我可能会在某些方面受到惩罚(?)。

【问题讨论】:

【参考方案1】:

如何减少 ECS 系统某些部分的鸭式打字? 更具体地说,再次启用可爱内容辅助的设计模式是什么?

一个想法是将您的组件实现视为您与系统交互的管道。无论如何,这就是他们的意图,成为一种影响行为的数据驱动方式。

class Physics : public Component<Physics> 
public:
  Vector3 GetVelocity() const;
  void SetVelocity(const Vector3& velocity);
private:
  Vector3 velocity_;

现在为了设置速度,只需调用:

Physics* physics = getComponent<Physics>( projectile->physic );
if ( physics ) 
  physics->SetVelocity( Vector3( 1, 0, 0 ) );

然后物理系统的工作是获取物理组件上的速度并将其与任何其他数据属性一起应用于内部物理模拟。

换句话说,将系统的输入状态视为当前组件值和先前系统发出的任何其他可变状态的组合。

除了避免您提到的鸭式打字之外,您还可以得到更容易理解和更容易流动的代码。它还为脚本系统和其他外部影响者通过操纵组件上的 getter/setter 轻松变异打开了大门。

【讨论】:

我花了一年多的时间才相信并接受这是一个正确的解决方案。谢谢。效果很好。

以上是关于减少实体组件系统中的鸭子打字劣势的主要内容,如果未能解决你的问题,请参考以下文章

如何从 Angular 6 中的另一个组件的打字稿中激活和停用组件中的样式?

无法访问父组件 React 打字稿中的转发 Ref 值

在打字稿中的基于 Vue 类的组件中键入 prop

基于打字稿类的组件中的Vuetify日历

打字稿反应组件中的反应/道具类型eslint错误

样式组件 + 打字稿:“as”不可分配给类型 IntrinsicAttributes