#c# #xna #collision #sliding
#c# #xna #столкновение #скольжение
Вопрос:
В моей игре на C # 3D: у меня есть OBB (ориентированная ограничительная рамка) для моей стены. Мой плеер — еще один крошечный obb. У меня хорошее обнаружение столкновений с использованием SAT (теорема о разделительной оси). Когда происходит столкновение, у меня есть старая позиция игрока (где столкновения не произошло) и изменение позиции, которое испытал игрок. Чтобы вычислить новую позицию, которую я использую: Position = OldPosition PositionChange;
у меня также есть функция, которая определяет, когда я сталкиваюсь с любой стеной в моем мире, она вернет null, если столкновения нет, и вернет стену, если есть столкновение. Стена — это класс, который я добавил, у которого есть модель, OBB и позиция. If (IntersectsAnyWall() == null) //no collision
Это работает хорошо, однако у меня нет скользящей работы. Под скольжением я подразумеваю, что когда игрок входит в стену под углом, он скользит по ней, а не просто останавливается. Разделение движения на компоненты X и Z, а затем тестирование их обоих по отдельности создает эффект дрожания, чего я не хочу.
Может кто-нибудь дать мне совет о том, как подойти к скольжению с столкновением OBB?
Ответ №1:
Стена может быть смоделирована так, чтобы останавливать только движения в направлении нормали стены. Чтобы разрешить скольжение, вы должны найти нормаль стены в месте столкновения. Кроме того, было бы неплохо рассчитать, насколько глубоко произошло столкновение. Тогда все, что вам нужно сделать, это вычесть «непроходимую» часть:
Position = OldPosition PositionChange
if(IntersectsAnyWall() != null)
{
var normal = //wall's normal at collision site
var collisionDepth = ...;
Position = collisionDepth * normal;
}
Если вы не можете вычислить глубину столкновения, вы также можете вычесть всю часть по нормали:
Position = OldPosition PositionChange
if(IntersectsAnyWall() != null)
{
var normal = //wall's normal at collision site
var partAlongNormal = Vector2.Dot(PositionChange, -normal);
Position = partAlongNormal * normal;
}