1

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

例子

这是一个coliru 演示

我的 ECS 中有 2 个系统:-

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

有 2 个组件类型 : Com_Projectile, Physics.

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

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));
    }
};

问题

基于上述代码段的真实程序可以正常工作。
但是,在编码时,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"
};

坏处:-

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

1 回答 1

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 轻松变异打开了大门。

于 2017-06-10T01:52:33.720 回答