ECS中的交错系统(实体组件系统)?

时间:2017-02-17 22:53:13

标签: entity-system

我正在努力为实体系统添加物理,并对ECS的系统部分感到困惑。

例如,在非ECS项目中,我可能会有这样的事情:

function updatePhysics()
    foreach(thisRobot in robots)
        thisRobot.move()
        foreach(otherRobot in robots)
            if(response = thisRobot.isColliding(otherRobot))
                thisRobot.resolveCollision(response)

然而,在ECS项目中,我将拥有一个运行在PositionComponent和VelocityComponent上的MovementSystem以及一个在PositionComponent和ShapeComponent上运行的CollisionSystem。结果如下:

MovementSystem
    function update()
        foreach(entity in entities)
            this.move(entity)

CollisionSystem
    function update()
        foreach(thisEntity in entities)
            foreach(otherEntity in entities)
                if(response = this.isColliding(thisEntity, otherEntity)
                    this.resolve(thisEntity, response)

不同之处在于,在非ECS版本中,移动和碰撞是交错的,而在ECS版本中它们是分开的。是否有正常的模式来模拟实体系统中的这种行为?我知道ECS的全部意义是远离继承,但也许运动系统和碰撞系统都是一个更通用的PhysicsSystem的一部分,它在一个单独的权限上调用其他系统更新函数而不是每个系统维护自己的循环?

3 个答案:

答案 0 :(得分:0)

并非所有移动的实体都受到模拟物理的影响......

我会将MovementSystem分成两种类型

  1. 受物理影响的实体的移动。
  2. 物理影响的实体的移动。
  3. 如果是后者,您可以继续MovementComponent上的方向并结合VelocityComponent上的速度,并计算实体的移动和位置。

    对于前者,您需要允许物理运行其模拟,确定碰撞并处理它们。在任何一种情况下,您都需要更新受物理影响的所有实体的位置。

    所以从循环的角度来看,我希望看到

    1. 输入系统捕获按键/鼠标输入。
    2. 播放器控制器系统分析输入并根据需要生成意图。
    3. 为受非物理影响的实体运行移动。
    4. 执行RigidBodyMovementSystem
    5. 解决冲突
    6. 更新所有受物理影响的实体的位置。
    7. 请记住,即使根据您描述系统的方式,也可以将它们分解为专门处理一个较小任务的较小系统组件,该步骤的输出是另一个系统的输入。

答案 1 :(得分:0)

直接的方法可以是将运动组件与实际目标一起添加到运动组件中。然后只更新运动系统中的前者 另一方面,碰撞系统将尝试通过使用所需位置切换来应用新位置,并一次检查一个实体的碰撞。

另一种方法可能是仅更新运动系统内的速度。然后添加一个更通用的物理系统,一次更新实体的位置并检查碰撞,根据需要调整速度和位置。

您甚至可以定义一个完全按照之前的方式运行的系统:迭代所有实体,一次更新实体的位置并检查冲突,然后继续下一个实体。
你没有必要将运动系统和碰撞系统分开,做对你和你的游戏有益的事情。

答案 2 :(得分:0)

在ECS结构中,您的运动系统不在乎物理。物理学将拥有自己的系统。

Position系统基于其他组件Velocity更新Physics组件。
Velocity系统根据作用力更新Collision组件。
Position系统会基于碰撞(与其他对象相交)来更新VelocityMovementSystem { void Process(Entity e){ e.GetComponent(PositionComponent).position += e.GetComponent(VelocityComponent).velocity; } } PhysicsSystem { void Process(Entity e){ e.GetComponent(VelocityComponent).velocity += World.gravity; //And other physical forces being applied to the entity. //I guess you could have a 'Forces' component. } } CollisionSystem { void Process(Entity e){ var collisions = SomeFunctionThatChecksCollisionsWithTheEntityInTheScene(e); foreach(collision in collisions) { e.GetComponent(VelocityComponent).velocity += SomeFunctionToApplyForceBasedOnCollision(collision); e.GetComponent(PositionComponent).position += SomeFunctionToOffsetAwayFromTheCollisionIntersection(collision); } } } 组件。

伪代码:

point(at:)