Unity's on collision event memberi Anda objek Collision yang memberi Anda beberapa informasi tentang collision yang terjadi (termasuk daftar ContactPoints dengan hit normals).
Tapi yang tidak Anda dapatkan adalah permukaan normal untuk collider yang Anda pukul. Berikut screenshot untuk diilustrasikan. Garis merah berasal dari ContactPoint.normal
dan garis biru dari RaycastHit.normal
.
Apakah ini merupakan contoh dari persembunyian informasi untuk menyediakan API yang disederhanakan? Atau apakah teknik deteksi tabrakan realtime 3D standar tidak mengumpulkan informasi ini?
Dan untuk bagian kedua dari pertanyaan, apa cara yang pasti dan relatif efisien untuk mendapatkan permukaan yang normal untuk tabrakan?
Saya tahu bahwa raycasting memberi Anda normals permukaan, tetapi sepertinya saya perlu melakukan beberapa raycast untuk mencapai ini untuk semua skenario (mungkin kombinasi titik kontak / normal melewatkan collider pada pemeran pertama, atau mungkin Anda perlu melakukan rata-rata semua normal poin kontak 'untuk mendapatkan hasil terbaik).
Metode saya saat ini:
Cadangkan
Collision.contacts[0].point
sepanjang hitnya normalRaycast ke hit normal dinegasikan untuk
float.MaxValue
, padaCollision.collider
Jika itu gagal, ulangi langkah 1 dan 2 dengan yang tidak dinegasikan normal
Jika gagal, coba langkah 1 hingga 3 dengan
Collision.contacts[1]
Ulangi 4 hingga berhasil atau sampai semua titik kontak habis.
Menyerahlah, kembali
Vector3.zero
.
Ini sepertinya menangkap semuanya, tetapi semua raycast itu membuat saya mual, dan saya tidak yakin bagaimana menguji apakah ini bekerja untuk cukup banyak kasus. Apakah ada cara yang lebih baik?
EDIT Jika ini memang benar-benar keadaannya dengan tabrakan 3D, tinjauan umum mengapa dalam kasus umum akan sama disambut sebagai sesuatu yang spesifik untuk Unity.
sumber
Jawaban:
Ini benar-benar seperti keadaan dengan tabrakan. Tidak hanya 3D, tetapi juga 2D. Ambil contoh berikut:
AABB hijau dan merah bertabrakan, dan manifold kontak adalah area biru. Titik kontak akan berada di area biru di suatu tempat (di mana tepatnya dapat bervariasi dengan algoritma, tetapi sudut tempat bertemu biru / merah / hijau adalah ideal-ish).
Permukaan normal apa yang harus dikembalikan? Tepi atas AABB merah atau tepi kiri? Jika kotak hijau jatuh, mungkin kita bisa menebak tepi atas. jika bergerak ke kanan, mungkin kita bisa menebak sisi kiri. Bagaimana jika itu bergerak ke bawah dan ke kanan? Apakah kita mengambil poros penetrasi paling sedikit? Sumbu kecepatan kecepatan terbesar? Beberapa heuristik dari keduanya? Bagaimana jika kotak-kotak itu akan bertabrakan persis di sudut-sudut?
Perluas ini ke permukaan 3D kompleks yang berpotensi terdiri dari 100-an tris / wajah. Anda masih hanya akan memiliki sejumlah kecil titik kontak ideal-ish. Permukaan normal apa yang harus dikembalikan? Permukaan rata-rata normal di seluruh tri-mesh (yang tidak masuk akal untuk sebagian besar objek)? Poin langsung "di bawah" sudut kotak bertabrakan (yang tidak didefinisikan dengan baik untuk sebagian besar bentuk lainnya)? Apakah Anda mencoba menemukan wajah terdekat dengan titik kontak yang dihasilkan (yang akan memerlukan lintasan kedua, karena titik kontak tidak dihitung secara langsung dari permukaan jala mana saja)? Jika Anda menemukan wajah terdekat, apakah Anda mengambil wajah normal atau apakah Anda menyisipkan simpul wajah pada titik kontak untuk mendapatkan normal yang benar untuk objek "halus"?
Sungguh, masalah utama adalah bahwa titik kontak tidak semua titik kontak. Dalam banyak kasus, itu akan menjadi set poin yang tak terbatas. Mereka hanya beberapa titik yang terdistribusi dengan baik yang membuatnya layak untuk memperkirakan reaksi fisik dengan menerapkan gaya pada titik-titik tersebut untuk mendorong benda bertabrakan di sekitar dengan cara reaslitic-ish. Poin / lokasi spesifik dari kontak objek aktual disarikan jauh di belakang model matematika yang disederhanakan. Oleh karena itu, gagasan permukaan kontak normal tidak masuk akal dalam kasus umum.
Tentu saja, dengan batasan dan batasan yang lebih spesifik pada objek, dunia, dan gerakan Anda, Anda dapat membuat algoritma tabrakan alternatif yang dapat memberi tahu Anda tentang permukaan normal. Dalam kasus 2D di atas, jika kita mengasumsikan bahwa kotak tidak pernah berputar dan kita tahu kecepatan relatif dan posisi terakhir masing-masing, akan dapat menggunakan deteksi tabrakan terus menerus untuk mencari tahu kapan mereka akan bertabrakan dan fitur yang bertabrakan, memasok kita dengan fitur yang tepat di mana tabrakan terjadi, yang kemudian dapat digunakan sebagai kontak / tabrakan / permukaan normal. Game platformer dibangun sepenuhnya berdasarkan asumsi dan trik khusus (Itulah sebabnya menggunakan perpustakaan fisika umum seperti Box2D atau Havok atau cahaya tidak pernah menghasilkan jenis kontrol yang ketat dan presisi yang Anda temukan di platformer klasik seperti Mario atau Sonic; Saya tidak akan melakukannya. ingin mengatakannya '
Perpustakaan fisika Newtonian umum, seperti yang digunakan di Unity3D, tidak dapat membuat semacam penyederhanaan dan asumsi. Karenanya, Anda tidak mendapatkan tabrakan permukaan normal, Anda mendapatkan manifold kontak, umumnya disederhanakan ke titik kontak, dan hanya itu.
sumber