Почему Unity OnCollisionEnter не дает мне поверхностные нормали, и какой самый надежный способ их получить?

11

Событие Unity по столкновению дает вам объект Collision, который дает вам некоторую информацию о произошедшем столкновении (включая список ContactPoints с нормалью попадания).

Но то, что вы не получаете, это поверхностные нормали для коллайдера, который вы ударили. Вот скриншот для иллюстрации. Красная линия от ContactPoint.normalи синяя линия от RaycastHit.normal.

введите описание изображения здесь

Является ли это примером того, как Unity скрывает информацию для предоставления упрощенного API? Или стандартные трехмерные методы обнаружения столкновений в реальном времени просто не собирают эту информацию?

И для второй части вопроса, каков верный и относительно эффективный способ получить нормальную поверхность для столкновения?

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

Мой текущий метод:

  1. Резервное копирование Collision.contacts[0].pointвдоль его удара нормально

  2. Raycast вниз отрицательный удар нормальный для float.MaxValue, наCollision.collider

  3. Если это не удается, повторите шаги 1 и 2 с неотрицательным нормальным

  4. Если это не помогло, попробуйте шаги 1–3 с Collision.contacts[1]

  5. Повторите 4 до успешного или пока все точки контакта не исчерпаны.

  6. Сдавайся, возвращайся Vector3.zero.

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

РЕДАКТИРОВАТЬ Если это действительно так, как обстоят дела с 3D-столкновением, обзор того, почему в общем случае будет так же приветствоваться, как что-то специфическое для Unity.

michael.bartnett
источник
Это просто из любопытства, или вы пытаетесь что-то сделать и застряли? То есть, почему вы думаете, что вам нужна нормальная поверхность? Задайте вопрос о том, какого эффекта вы пытаетесь достичь, а не о том, как «исправить» решение неустановленной проблемы, и кто-то может помочь вам решить ее. :)
Шон Миддледич
@SeanMiddleditch Я не согласен. Вопрос хорошо поставлен, и это именно то, что я искал. Этот вопрос и его ответы помогли мне исправить некоторые вещи, которые я делал неправильно.
SteakOverflow

Ответы:

12

Это действительно так, как обстоят дела со столкновением. Не только 3D, но и 2D. Возьмите следующий пример:

Перекрывающиеся AABB

Зеленые и красные AABB сталкиваются, а контактный коллектор - синяя область. Точки соприкосновения будут где-то в синей области (именно там, где может меняться алгоритм, но углы, где встречаются синий / красный / зеленый, идеальны).

Какая нормальная поверхность должна быть возвращена? Верхний край красного AABB или левый край? Если зеленый прямоугольник падает, возможно, мы можем разумно угадать верхний край. если он движется вправо, может быть, мы сможем угадать левый край. Что, если он двигался вниз и вправо? Берем ли мы ось наименьшего проникновения? Ось скорости наибольшей скорости? Некоторая эвристика обоих? Что если бы ящики столкнулись именно по углам?

Расширьте это до сложной трехмерной поверхности, потенциально состоящей из сотен трис / граней. У вас все еще будет небольшое количество контактных точек с идеальными контактами. Какая нормальная поверхность должна быть возвращена? Средняя поверхность, нормальная по всей три-сетке (что не имеет смысла для большинства объектов)? Точки непосредственно «под» углами сталкивающегося прямоугольника (которые не очень хорошо определены для большинства других фигур)? Пытаетесь ли вы найти ближайшую грань к сгенерированным контактным точкам (что потребует второго прохода, поскольку контактные точки не рассчитываются напрямую из каких-либо граней сетки)? Если вы находите ближайшее лицо, берете ли вы нормаль лица или интерполируете вершины лица в точке контакта, чтобы получить правильную нормаль для «гладких» объектов?

Действительно, основная проблема заключается в том, что точки контакта - это не все точки контакта. Во многих случаях это было бы бесконечным набором точек, в конце концов. Это всего лишь несколько точек, которые хорошо распределены, что позволяет разумно приблизиться к физической реакции, применяя силы в указанных точках, чтобы толкать сталкивающиеся объекты вокруг в реаслитике. Конкретные точки / места фактического контакта объекта абстрагируются за упрощенной математической моделью. Следовательно, идея конкретной нормальной поверхности контакта просто не имеет большого смысла в общем случае.

Конечно, с более конкретными ограничениями и ограничениями на ваши объекты, мир и движение вы можете создавать альтернативные алгоритмы столкновения, которые могут рассказать вам о нормальной поверхности. В приведенном выше 2D-случае, если мы предположим, что ящики никогда не вращаются и что мы знаем относительную скорость и последнюю позицию каждого из них, можно было бы использовать непрерывное обнаружение столкновений, чтобы точно определить, когда они сталкиваются и какие объекты столкнулись, предоставляя нам точный объект, где произошло столкновение, которое затем может быть использовано как нормальный контакт / столкновение / поверхность. Платформерные игры построены исключительно на таких предположениях и специальных хитростях (вот почему использование общей библиотеки физики, такой как Box2D или Havok, или свет никогда не дает такого жесткого, точного управления, как у классических платформеров, таких как Mario или Sonic; я бы не стал хочу сказать это

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

Шон Миддледич
источник
Это фантастический ответ, и именно то, что я искал, спасибо. Конкретной проблемой было получение убедительного вектора отражения на кинематическом твердом теле при столкновении. Является ли обычным подходом, если вы хотите, чтобы такого рода информация выбирала, хотите ли вы использовать радиопередачу или захватить 3 контактные точки (если они есть) и использовать перекрестный продукт?
michael.bartnett