Войти
ПрограммированиеФорумФизика

[Решено] Обработка столкновений в экшн-играх с прямым управлением

#0
(Правка: 15:57) 15:37, 5 мая 2020

Допустим, разрабатывается игра:

  • двухмерная бродилка с видом сверху
  • стены могут быть под любыми углами.
  • персонажи могут двигаться под любым углом.

  • Хотелось бы реализовать самую обычную до-хавокскую шутерную физику.

    1. Начался кадр, известен вектор, на который персонаж должен сместиться согласно заданному игроком направлению.
    2. Итак, пробуем продвинуться.
    3. Нет препятствий - все просто.
    4. Коллизия со стеной - вычисляем расстояние до поверхности стены и отодвигаемся назад на разницу. Вроде все корректно - эта точка будет гарантировано свободна, но персонаж будет тормозиться об стены, а надо чтобы скользил как в старых добрых экшенах.
    5. Хорошо, тогда отодвигаем персонажа назад не вдоль изначального вектора движения, а вдоль нормали стены. Выглядит убедительно в простом случае.
    6. Но, что если в новой точке тоже будет коллизия? куда теперь двигаться? опять по нормали? Но при обработке столкновения со вторичным препятствием надо все еще помнить о первом, а что если геометрия в точке оказалась достаточно сложная и при обработке вторичного столкновения появится еще одно и так далее... как-то неопределенно это все выглядит.

    Что делать? Каковы стандартные подходы?

    PS: кажется, есть идея: при обработке вторичного столкновения уже забить на скольжение и возвращаться назад. но вдоль какого вектора и насколько? и вроде как это не гарантирует отсутствие N-х столкновений... в общем, тоже так себе выглядит.

    PS2: еще идея. после первичного столкновения отодвигаться назад на разницу в расстоянии до поверхности. А затем том же кадре вызвать ту же процедуру передвижения, но в качестве вектора выбрать касательный к поверхности, укороченный в соответствии с "остатком движения" и косинусом угла. Повторять N раз, либо пока "остаток движения" не исчерпается


    #1
    16:06, 5 мая 2020

    kkolyan
    > Каковы стандартные подходы?
    Выталкивают сначала по нормали первого столкновения, потом второго, потом снова первого и опять второго — и так N раз. В общем, по всему списку контактов проходят N раз в цикле. Еще выталкивают обычно не целиком, а, скажем, до 0.9 глубины погружения на один шаг (не итерацию цикла, а за весь) физики.
    В общем, почитай про псевдоскорости в физических движках — это как раз про это.

    #2
    (Правка: 16:47) 16:24, 5 мая 2020

    }:+()___ [Smile]
    спасибо! надо подумать.
    почему в той же юньке из коробки нет приблуды для такого? казалось бы, почти во всех экшнах это одинаково работает.

    #3
    (Правка: 4:43) 4:37, 22 мая 2020

    Добрался до реализации сабжа. Вдохновившись подсказкой выше, реализовал и все работает как надо.

    Псевдокод для интересующихся решением:

        Vector position;
    
        void move(Vector movement, int iterations) {
            for (int i = 0; i < iterations; i++) {
                position += movement / iterations;
                Collision[] collisions = findCollisions(position);
                for (Collision collision: collisions) {
                    position += collision.normal * collision.depth;
                }
            }
        }
    В моем случае работает хорошо при кол-ве итераций 4. Для быстрого движения (относительно размера хитбокса) нужно больше.

    #4
    22:18, 22 мая 2020

    kkolyan
    > Псевдокод для интересующихся решением:
    Не, не так. Это у тебя уменьшенный шаг физики и одна итерация разрешения коллизий вместо N.
    В общем, еще раз советую почитать статьи по физдвижкам в секции "резрешение коллизий".

    #5
    (Правка: 3:11) 0:01, 23 мая 2020

    }:+()___ [Smile]
    потестировал свой вариант - выглядит будто все работает как надо. пожалуйста, поясни, чем именно мне грозит мое решение? без понимания какие именно проблемы это решит, закапываться в статьи не очень-то оправданно - в разработке игры еще есть чем заняться, мягко говоря.

    #6
    6:27, 27 мая 2020

    kkolyan
    > поясни, чем именно мне грозит мое решение?
    Некорректное выталкивание из нескольких препятствий: может быть как слишком много, так и недостаточно.
    Низкая производительность: ты N раз ищешь коллизии, тогда как в классическом алгоритме это делается один раз.

    ПрограммированиеФорумФизика