Чередование систем в 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 на два типа

  1. Движение для сущностей, которые находятся под влиянием физики.
  2. Движение для сущностей, которые не подвержены влиянию физики.

В случае последнего, вы можете пойти дальше и взять направление на MovementComponent в сочетании со скоростью на VelocityComponent и рассчитать движение и положение объекта.

В первом случае вам нужно разрешить физике запускать симуляцию, определять столкновения и обрабатывать их. В любом случае вам нужно будет обновить положение для всех объектов, на которые влияет физика.

Так что с точки зрения цикла я бы ожидал увидеть

  1. Система ввода фиксирует ввод с помощью клавиш / мыши.
  2. Система контроллера игрока анализирует ввод и генерирует намерение соответствующим образом.
  3. Запустите движение для объектов, не подверженных физике.
  4. Выполнить RigidBodyMovementSystem
  5. Разрешить столкновения
  6. Обновить положение для всех объектов, на которые влияют физики.

Помните, что даже в зависимости от того, как вы описываете свои системы, они могут быть разложены на более мелкие системные компоненты, которые специально выполняют одну меньшую задачу, и результат этого шага является входом для другой системы.

Другие вопросы по тегам