Ответ 1
Игровые движки обычно моделируют время серией дискретных шагов. Как следствие, система столкновений может попасть в сложные (дорогостоящие в вычислительном отношении) случаи из-за взаимопроникновения (ваш случай) или из-за того, что все движется быстро -tunneling, где A находится на одной стороне B на этапе N и полностью на другой стороне B на этапе N + 1. Еще сложнее, если вам нужно иметь дело с многотельным или непрерывным контактом или с невыпуклым, сочлененным или мягким объектом. Хлоп! мы моделируем весь мир.
Вы хотите заняться "игровой физикой" и использовать приближения, чтобы выкупить частоту смены кадров... В конце концов, вы можете покрыть большую часть ошибки кучей дыма или легких вспышек. :-)
Существует класс алгоритмов, которые явно учитывают моделируемое время, чтобы помочь системе столкновений. Существует много способов реализовать систему "непрерывного обнаружения столкновений". Вы можете начать здесь, но прежде чем приступить к написанию кода, вам следует прочитать широко. К счастью, есть много литературы о столкновениях. вот хорошее место для начала https://docs.unity3d.com/Manual/ContinuousCollisionDetection.html https://pybullet.org/Bullet/phpBB3/viewtopic.php?t=20
Вот один из предложенных эвристических методов, которые могут работать в вашей существующей системе... Этот эвристический метод может работать в такой игре, как астроиды 3d, где объекты свободно перемещаются в пространстве. Это может быть достаточно для того, что вам нужно.
Изображение каждого объекта хранит свой текущий вектор состояния (положение, ориентация, скорость, ускорение, вращение...) и его предыдущий вектор состояния с предыдущего временного шага.
Предположим, вы обнаружили потенциальное коллизия между объектами A и B в момент времени = текущий.
Если время = предыдущее, предположим, что А и В не соприкасаются.
Вычислить ближайшие точки на поверхностях A и B, соответственно, в момент времени = prev, используя предыдущие векторы состояния A и B. (closestA, closestB).
Сегмент линии (closestA, closestB) будет иметь ненулевую длину в момент времени = предыдущий. Вы можете просто использовать closestB для вашей позиции и нормали, но это будет иметь некоторую ошибку, пропорциональную длине отрезка линии.
Поэтому выполните бинарный поиск по времени и минимизируйте ошибку, найдя время, когда A сколь угодно близко к B. При каждом проходе поиска уменьшайте размер шага времени поиска пополам. 0,5, 0,25, 0,125.. до тех пор, пока длина (closestA, closestB) не станет ниже порога ошибки, или вы не сдадитесь.
Это должно дать вам приемлемое приблизительное решение для простых случаев...
Кроме того, вы сказали, что вы используете теорему об отделении в качестве "первой проверки". Это действительно звучит дорого для меня, если это действительно "первая проверка"..
Самое быстрое вычисление - это то, что вы не делаете, поэтому быстрое коллизия означает много дешевых предварительных испытаний и позволяет избежать дорогостоящих случаев.
Вы можете рассмотреть возможность использования пространственных методов, таких как грубая пространственная сетка, и проверять только объекты, которые, как вы уже знаете, находятся рядом друг с другом.
Кроме того, тест сфера-сфера - это очень быстрый предварительный тест, чтобы увидеть, перекрывают ли ограничивающие сферы двух выпуклых объектов.