首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >减少实体组件系统中鸭类的缺点

减少实体组件系统中鸭类的缺点
EN

Stack Overflow用户
提问于 2017-05-24 02:17:26
回答 1查看 279关注 0票数 1

如何减少实体组件系统中的鸭类现象?

示例

这是一个coliru演示

在我的ECS中有两个系统:-

System_Projectile:管理所有弹丸和子弹方面。

System_Physic:管理物理的组成部分。

有两个组件类型:Com_ProjectilePhysics.。

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

代码语言:javascript
复制
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)

代码语言:javascript
复制
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类型的任何physic语义线索。 (变量名称和注释除外)
  • 因此,我必须对此保持意识。 编码器对类型的误解只会在运行时检测到. 然而,在实践中,这种错误很少发生。
  • 我必须回想起可以做我想做的事情的系统名称(System_Physic::), 然后回忆函数的名称(在本例中为System_Physic::setVelocity())。
  • 总之,我的大脑有很多间接的方向。

在我过去的日子里,当我使用大量的(深)继承时,它要容易得多,就像这样:

代码语言:javascript
复制
    physic->setVelocity(Vec3(1,0,0));

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

问题

如何减少某些ECS系统中的鸭型?

更具体地说,什么是设计模式,使可爱的内容-协助再次?

我现在的解决办法

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

代码语言:javascript
复制
class Com_Projectile{
    public: Physics* physic; //edited from "Entity* physic"
};

Disadvantage:-

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

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-06-10 01:52:33

如何减少某些ECS系统中的鸭型? 更具体地说,什么是设计模式,使可爱的内容-协助再次?

其中一个想法是将组件实现视为与系统交互的管道。不管怎样,这就是他们的意图,是一种数据驱动的方式来影响行为。

代码语言:javascript
复制
class Physics : public Component<Physics> {
public:
  Vector3 GetVelocity() const;
  void SetVelocity(const Vector3& velocity);
private:
  Vector3 velocity_;
}

现在,为了设置速度,这是一个简单的调用:

代码语言:javascript
复制
Physics* physics = getComponent<Physics>( projectile->physic );
if ( physics ) 
  physics->SetVelocity( Vector3( 1, 0, 0 ) );

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

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

除了避免您提到的鸭子类型之外,您还得到了更容易理解的代码,而且代码流也更容易。它还打开了容易被脚本系统和其他外部影响者变异的大门,所有这些都是通过操纵组件上的getter/setter来实现的。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/44147862

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档