Por que o OnCollisionEnter da Unity não me fornece normais de superfície e qual é a maneira mais confiável de obtê-los?

11

O evento Unity's on collision fornece um objeto Collision que fornece algumas informações sobre a colisão que ocorreu (incluindo uma lista de ContactPoints com normais de ocorrência).

Mas o que você não obtém são normais de superfície para o colisor atingido. Aqui está uma captura de tela para ilustrar. A linha vermelha é de ContactPoint.normale a linha azul é de RaycastHit.normal.

insira a descrição da imagem aqui

Essa é uma instância de informações ocultas do Unity para fornecer uma API simplificada? Ou as técnicas padrão de detecção de colisão em tempo real 3D simplesmente não coletam essas informações?

E para a segunda parte da pergunta, qual é a maneira certa e relativamente eficiente de obter uma superfície normal para uma colisão?

Eu sei que o raycasting fornece normais de superfície, mas parece que eu preciso fazer vários raycasts para fazer isso em todos os cenários (talvez uma combinação de ponto de contato / normal perca o colisor no primeiro elenco ou talvez você precise fazer uma média de tudo normais dos pontos de contato para obter o melhor resultado).

Meu método atual:

  1. Faça backup do Collision.contacts[0].pointseu hit normal

  2. Raycast abaixo o hit negado normal para float.MaxValue, emCollision.collider

  3. Se isso falhar, repita as etapas 1 e 2 com a função normal não negada.

  4. Se isso falhar, tente as etapas 1 a 3 com Collision.contacts[1]

  5. Repita 4 até obter êxito ou até que todos os pontos de contato tenham se esgotado.

  6. Desista, volte Vector3.zero.

Isso parece pegar tudo, mas todos esses raycasts me deixam enjoado e não sei como testar se isso funciona em casos suficientes. Existe uma maneira melhor?

EDITAR Se realmente é assim que as coisas acontecem com a colisão 3D, uma visão geral do porquê, no caso geral, seria tão bem-vinda quanto algo específico do Unity.

michael.bartnett
fonte
Isso é apenas por curiosidade, ou você está tentando fazer alguma coisa e ficar preso? Ou seja, por que você acha que precisa da superfície normal? Faça uma pergunta sobre o efeito que você está tentando alcançar, em vez de como "consertar" uma solução para um problema não especificado, e alguém poderá ajudá-lo a resolvê-lo. :)
Sean Middleditch
@SeanMiddleditch Não concordo. A questão está bem colocada e é exatamente o que eu estava procurando. Esta pergunta e suas respostas me ajudaram a corrigir algumas coisas que eu estava fazendo de errado.
SteakOverflow

Respostas:

12

Realmente é assim que as coisas acontecem com a colisão. Não apenas 3D, mas também 2D. Veja o seguinte exemplo:

AABBs sobrepostos

Os AABBs verde e vermelho estão colidindo e o coletor de contato é a área azul. Os pontos de contato estarão na área azul em algum lugar (exatamente onde pode variar com o algoritmo, mas os cantos onde o azul / vermelho / verde se encontra são ideais).

Que superfície normal deve ser devolvida? A borda superior do AABB vermelho ou a borda esquerda? Se a caixa verde estiver caindo, talvez possamos adivinhar razoavelmente a borda superior. se estiver se movendo para a direita, talvez possamos adivinhar razoavelmente a borda esquerda. E se estivesse se movendo para baixo e para a direita? Tomamos o eixo de menor penetração? O eixo de velocidade de maior velocidade? Alguma heurística de ambos? E se as caixas colidissem exatamente nos cantos?

Estenda isso para uma superfície 3D complexa, potencialmente composta de 100s de tris / faces. Você ainda terá apenas um pequeno número de pontos de contato ideais. Que superfície normal deve ser devolvida? A superfície média normal em toda a malha dupla (o que não faz sentido para a maioria dos objetos)? Os pontos diretamente "embaixo" dos cantos da caixa de colisão (que não estão bem definidos para a maioria das outras formas)? Você tenta encontrar a face mais próxima dos pontos de contato gerados (o que exigiria uma segunda passagem, já que os pontos de contato não são calculados diretamente de nenhuma face da malha)? Se você encontrar a face mais próxima, considera a normal da face ou interpola os vértices da face no ponto de contato para obter a normal correta para objetos "suaves"?

Realmente, o principal problema é que os pontos de contato não são todos . Em muitos casos, isso seria um conjunto infinito de pontos, afinal. São apenas alguns pontos bem distribuídos que tornam razoavelmente possível aproximar a reação física aplicando forças nesses pontos para empurrar os objetos em colisão de maneira reaslítica. Os pontos / locais específicos do contato real com o objeto são abstraídos por trás de um modelo matemático simplificado. Portanto, a idéia de uma superfície específica normal de contato simplesmente não faz muito sentido no caso geral.

Obviamente, com restrições e limitações mais específicas em seus objetos, mundo e movimento, você pode criar algoritmos de colisão alternativos que podem falar sobre a superfície normal. No caso 2D acima, se assumirmos que as caixas nunca giram e que sabemos a velocidade relativa e a última posição de cada uma delas, poderia usar a detecção de colisão contínua para descobrir exatamente quando elas colidiriam e quais recursos colidiram, fornecendo-nos o característica exata onde ocorreu a colisão, que poderia então ser usada como um contato / colisão / superfície normal. Os jogos de plataformas são construídos inteiramente com base em suposições e truques especiais (é por isso que usar uma biblioteca de física geral como Box2D ou Havok ou a luz nunca produz o tipo de controle preciso e preciso que você encontra em plataformas clássicas como Mario ou Sonic; eu não faria isso quer dizer '

Bibliotecas gerais de física newtoniana, como a usada no Unity3D, não podem fazer esse tipo de simplificação e suposição. Portanto, você não obtém normais de superfície de colisão, obtém um coletor de contato, geralmente simplificado até os pontos de contato, e é isso.

Sean Middleditch
fonte
Esta é uma resposta fantástica, e exatamente o que eu estava procurando, obrigado. O problema específico era obter um vetor de reflexão convincente em um corpo rígido cinemático em colisão. É a abordagem usual se você deseja que esse tipo de informação escolha se deseja transmitir um broadcast ou pegar 3 pontos de contato (se disponível) e usar o produto cruzado?
Michael.bartnett 18/10/12