Чередование систем в ECS (система компонентов объекта)?
Я работаю над добавлением физики в 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 у меня будет MovementSystem, которая работает с PositionComponent и VelocityComponent, а также CollisionSystem, которая работает с 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, так и CollisionSystem является частью более общей PhysicsSystem, которая вызывает функции обновления других систем по одному праву, а не в каждой системе, поддерживающей свои собственные циклы?
2 ответа
Простым подходом может быть добавление к компоненту движения желаемого пункта назначения наряду с фактическим. Затем обновите только первое в системе движения.
С другой стороны, система столкновений будет пытаться применить новую позицию, переключая ее на желаемую, и проверять столкновения по одному объекту за раз.
Другим подходом может быть обновление только скоростей внутри системы движения. Затем добавьте более общую физическую систему, которая обновляет положение объекта одновременно и проверяет наличие столкновений, корректируя скорость и положение, если это необходимо.
Вы даже можете определить единственную систему, которая будет делать то же, что вы делали ранее: выполнять итерацию по всем объектам, обновлять позицию для объекта за раз и проверять наличие коллизий, а затем переходить к следующему объекту.
Вам не обязательно разделять систему движений и систему столкновений, делать то, что хорошо для вас и вашей игры.
В структуре ECS ваша система движений не заботится о вашей физике. У физики будет своя собственная система.
В Movement
система обновляет Position
компонент, основанный на каком-то другом компоненте, скажем, Velocity
.
В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
и рассчитать движение и положение объекта.
В первом случае вам нужно разрешить физике запускать симуляцию, определять столкновения и обрабатывать их. В любом случае вам нужно будет обновить положение для всех объектов, на которые влияет физика.
Так что с точки зрения цикла я бы ожидал увидеть
- Система ввода фиксирует ввод с помощью клавиш / мыши.
- Система контроллера игрока анализирует ввод и генерирует намерение соответствующим образом.
- Запустите движение для объектов, не подверженных физике.
- Выполнить RigidBodyMovementSystem
- Разрешить столкновения
- Обновить положение для всех объектов, на которые влияют физики.
Помните, что даже в зависимости от того, как вы описываете свои системы, они могут быть разложены на более мелкие системные компоненты, которые специально выполняют одну меньшую задачу, и результат этого шага является входом для другой системы.