我正在努力将物理添加到实体系统中,并对ECS的系统一部分感到困惑。
例如,在非ECS项目中,我可能有类似的东西:
function updatePhysics()
foreach(thisRobot in robots)
thisRobot.move()
foreach(otherRobot in robots)
if(response = thisRobot.isColliding(otherRobot))
thisRobot.resolveCollision(response)
然而,在ECS项目中,我将拥有一个在位置组件和速度component上运行的运动系统,以及在PositionComponent和ShapeComponent上运行的碰撞系统。结果是:
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的全部要点是摆脱继承,但是也许拥有Movementsystem和CollisisySystem是更通用的物理系统的一部分,该物理系统称其为其他系统更新在单个功能上的功能,而不是每个系统维护自己的循环?
一种直接的方法可以是将所需目的地与实际目标添加到运动组件中。然后仅更新运动系统中的前者。
另一方面,碰撞系统将尝试通过使用所需的一个切换新位置并一次检查一个实体。
另一种方法可能是仅更新运动系统中的速度。然后添加一个更通用的物理系统,该系统一次更新实体的位置,并检查碰撞,根据需要调整速度和位置。
您甚至可以定义一个单个系统,该系统完全可以完成您以前所做的工作:迭代所有实体,一次更新一个实体的位置并检查碰撞,然后继续使用下一个实体。
您不一定要分开移动系统和碰撞系统,请执行听起来对您和您的游戏有益的事情。
在ECS结构中,您的运动系统不在乎您的物理。物理学将具有自己的系统。
Movement
系统基于其他组件(例如Velocity
。
)更新Position
组件Physics
系统根据力更新Velocity
组件。Collision
系统根据碰撞(与其他对象相交)更新Position
和Velocity
组件。
伪代码:
MovementSystem {
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);
}
}
}
并非每个移动的实体都受模拟中物理的影响...
我会将MovementSystem
分为两种类型
- 对受影响的实体的运动。
- 对不影响物理的实体的运动。
在后者的情况下,您可以继续前进,并将MovementComponent
的方向与VelocityComponent
上的速度结合使用并计算实体的运动和位置。
对于前者,您将需要允许物理进行模拟,确定碰撞并处理这些模拟。无论哪种情况,您都需要更新所有受物理影响的实体的位置。
所以从循环的角度来看,我希望看到
- 输入系统捕获密钥/鼠标输入。
- 玩家控制器系统分析输入并适当生成意图。
- 运行非物理的运动影响实体。
- 执行僵化的机态
- 解决碰撞
- 所有影响实体的更新位置。
请记住,即使根据您描述系统的描述,它们也可以分解为较小的系统组件,这些系统组件专门处理一个较小的任务,该步骤的输出也是另一个系统的输入。