Perché OnCollisionEnter di Unity non mi offre le normali di superficie e qual è il modo più affidabile per ottenerle?


11

L'evento in caso di collisione di Unity ti dà un oggetto Collisione che ti fornisce alcune informazioni sulla collisione avvenuta (incluso un elenco di ContactPoints con hit standard ).

Ma ciò che non ottieni sono normali di superficie per il collisore che colpisci. Ecco uno screenshot per illustrare. La linea rossa proviene da ContactPoint.normale la linea blu proviene da RaycastHit.normal.

inserisci qui la descrizione dell'immagine

È un'istanza di Unity che nasconde informazioni per fornire un'API semplificata? Oppure le tecniche di rilevamento delle collisioni 3D in tempo reale standard non raccolgono queste informazioni?

E per la seconda parte della domanda, qual è un modo sicuro e relativamente efficiente per ottenere una superficie normale per una collisione?

So che il raycasting ti dà le normali di superficie, ma sembra che devo realizzare diversi raycast per realizzarlo in tutti gli scenari (forse un punto di contatto / una combinazione normale manca il collider nel primo cast, o forse devi fare una media di tutto le normali dei punti di contatto per ottenere il miglior risultato).

Il mio metodo attuale:

  1. Eseguire il backup Collision.contacts[0].pointlungo il suo colpo normale

  2. Trasmetti il ​​colpo negato normale per float.MaxValue, suCollision.collider

  3. In caso contrario, ripetere i passaggi 1 e 2 con la normale non negata

  4. In caso contrario, prova i passaggi da 1 a 3 con Collision.contacts[1]

  5. Ripetere 4 fino al completamento o fino all'esaurimento di tutti i punti di contatto.

  6. Rinuncia, ritorna Vector3.zero.

Questo sembra catturare tutto, ma tutti quei raycast mi fanno sentire nauseato, e non sono sicuro di come testarlo per un numero sufficiente di casi. Esiste un modo migliore?

MODIFICA Se questo è davvero il modo in cui le cose si verificano con la collisione 3D, una panoramica del perché nel caso generale sarebbe il benvenuto come qualcosa di specifico per Unity.


È solo per curiosità o stai cercando di fare qualcosa e rimanere bloccato? Cioè, perché pensi di aver bisogno della superficie normale? Fai una domanda su quale effetto stai cercando di ottenere, piuttosto che su come "risolvere" una soluzione a un problema non specificato e qualcuno potrebbe essere in grado di aiutarti a risolverlo. :)
Sean Middleditch,

@SeanMiddleditch Non sono d'accordo. La domanda è ben formulata ed è esattamente quello che stavo cercando. Questa domanda e le sue risposte mi hanno aiutato a correggere alcune cose che stavo facendo di sbagliato.
SteakOverflow

Risposte:


12

Questo è davvero il modo in cui le cose vanno in collisione. Non solo 3D, ma anche 2D. Prendi il seguente esempio:

AABB sovrapposti

Gli AABB verdi e rossi si scontrano e il collettore di contatto è l'area blu. I punti di contatto saranno nell'area blu da qualche parte (esattamente dove può variare con l'algoritmo, ma gli angoli in cui il blu / rosso / verde si incontrano sono ideali).

Quale superficie normale dovrebbe essere restituita? Il bordo superiore dell'AABB rosso o il bordo sinistro? Se la casella verde sta cadendo, forse possiamo ragionevolmente indovinare il bordo superiore. se si sta muovendo a destra, forse possiamo ragionevolmente indovinare il bordo sinistro. E se si stesse muovendo verso il basso e giusto? Prendiamo l'asse di minor penetrazione? L'asse di velocità della massima velocità? Qualche euristica di entrambi? E se le scatole si fossero scontrate esattamente agli angoli?

Estendilo a una superficie 3D complessa potenzialmente composta da centinaia di tris / facce. Avrai ancora un numero limitato di punti di contatto ideali. Quale superficie normale dovrebbe essere restituita? La superficie media normale su tutta la tri-mesh (che non ha senso per la maggior parte degli oggetti)? I punti direttamente "sotto" gli angoli della scatola di collisione (che non sono ben definiti per la maggior parte delle altre forme)? Cerchi di trovare la faccia più vicina ai punti di contatto generati (il che richiederebbe un secondo passaggio, poiché i punti di contatto non vengono calcolati direttamente dalle facce di una mesh)? Se trovi la faccia più vicina, prendi la faccia normale o interpoli i vertici della faccia nel punto di contatto per ottenere la normale corretta per gli oggetti "lisci"?

In realtà, il problema principale è che i punti di contatto non sono tutti i punti di contatto. In molti casi, questo sarebbe un insieme infinito di punti, dopo tutto. Sono solo alcuni punti che sono ben distribuiti che rendono ragionevolmente possibile approssimare la reazione fisica applicando forze in detti punti per spingere gli oggetti in collisione in un modo reaslitico. I punti / posizioni specifici del contatto reale dell'oggetto vengono sottratti dietro un modello matematico semplificato. Quindi, l'idea di una normale superficie di contatto normale semplicemente non ha molto senso nel caso generale.

Naturalmente, con vincoli e limitazioni più specifici su oggetti, mondo e movimento, è possibile creare algoritmi di collisione alternativi in ​​grado di parlarvi della normale alla superficie. Nel caso 2D sopra, se assumiamo che le scatole non ruotino mai e che conosciamo la velocità relativa e l'ultima posizione di ciascuna, potremmo usare il rilevamento continuo della collisione per scoprire esattamente quando si scontrerebbero e quali caratteristiche si scontrerebbero, fornendoci il caratteristica esatta in cui si è verificata la collisione, che potrebbe quindi essere utilizzata come contatto / collisione / superficie normale. I giochi platform si basano interamente su tali presupposti e trucchi speciali (motivo per cui l'utilizzo di una libreria di fisica generale come Box2D o Havok o la luce non produce mai il tipo di controllo stretto e preciso che trovi nei platform classici come Mario o Sonic; voglio dirlo '

Le librerie generali di fisica newtoniana, come quella usata in Unity3D, non possono fare questo tipo di semplificazioni e ipotesi. Pertanto, non si ottengono normali della superficie di collisione, si ottiene un collettore di contatto, generalmente semplificato fino ai punti di contatto, e basta.


Questa è una risposta fantastica, ed esattamente quello che stavo cercando, grazie. Il problema specifico era ottenere un vettore di riflessione convincente su un corpo rigido cinematico in caso di collisione. È il solito approccio se si desidera che questo tipo di informazioni scelga se si desidera trasmettere in streaming o acquisire 3 punti di contatto (se disponibili) e utilizzare il prodotto incrociato?
michael.bartnett,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.