Mengapa masker layer Unity perlu menggunakan bit shifting?


10

Saya akhirnya tahu mengapa layer mask saya untuk kode tumbukan tanah saya tidak berfungsi. Saya menggunakan NameToLayer()untuk mendapatkan layer yang saya butuhkan, tetapi layer mask menggunakan bit shifting untuk benar-benar menetapkan nilai layer mask. Ini sangat tidak biasa dan saya tidak melihat alasan mengapa ini tidak ditangani dalam kode di belakang. Mengapa kita harus menggunakan kode seperti ini:

mask = 1 << LayerMask.NameToLayer("Default");

ketika sesuatu seperti ini:

mask = LayerMask.NameToLayer("Default");

masuk akal lebih intuitif dan bekerja mirip dengan sisa Unity API?


2
Menggunakan versi string membutuhkan lebih banyak kekuatan pemrosesan. Belum lagi string secara internal adalah array yang merupakan tipe referensi dan akan ditambahkan ke pengumpul sampah.
Krythic

Jawaban:


3

Ini sangat performant. Hanya itu yang ada padanya - membandingkan string sebagai contoh yang jelas lebih lambat dengan faktor 10. Dan perhitungan fisika harus sangat dioptimalkan, jadi ada baiknya bahwa seseorang yang tahu apa yang terjadi menulisnya dengan cara ini.

Jadi pertanyaan tindak lanjut yang jelas adalah - mengapa ini tidak dibungkus dengan metode pembantu untuk menangani konversi dan pergeseran bit. Saya pikir tidak ada yang benar-benar melakukannya - saya telah menggulung utilitas pembantu yang bagus dan itu adalah praktik umum.


1
Pilihan desain yang benar oleh tim Unity adalah menggunakan integer sebagai pengindeks, bukan string. Saya merasa ngeri ketika saya berpikir tentang betapa gilanya para pengumpul sampah dengan implementasi mereka saat ini, belum lagi alokasi string array.
Krythic

1
Tentu saja - array apa pun sebaiknya dirujuk oleh bilangan bulat. Bilangan bulat dapat dengan mudah dibaca oleh manusia dengan enum sederhana.
Jordan Georgiev

Implementasi yang cepat dan kotor berfungsi, tetapi untuk proyek yang lebih besar saya menggunakan [Type Safe] ( assetstore.unity3d.com/en/#!/content/35903 ).
Jordan Georgiev

20

Menggunakan bit shifting memungkinkan Anda untuk memperhitungkan banyak lapisan dalam satu operasi fisika:

 Physics.Raycast(ray, out hitInfo, Mathf.Infinity, layerMask )

Tanpa menggeser sedikit, Anda akan diizinkan untuk raycast dalam satu layer dan hanya satu. Sementara dengan sedikit pergeseran, Anda dapat raycast di beberapa lapisan tertentu:

layerMask = (1 << LayerMask.NameToLayer("MyLayer1")) | (1 << LayerMask.NameToLayer("MyLayer2")) ;

Anda juga dapat raycast di setiap lapisan kecuali yang spesifik:

layerMask = (1 << LayerMask.NameToLayer("MyLayer1")) | (1 << LayerMask.NameToLayer("MyLayer2")) ;
layerMask = ~layerMask;

Jika Anda melihat "Manajer layer" di Unity, layer dapat dilihat sebagai indeks array satu dimensi yang sederhana .


EDIT: Saya belum pernah melihatnya sebelumnya, tetapi LayerMaskkelas memiliki fungsi utilitas untuk mendapatkan lapisan "dikomputasi" diberi nama lapisan:

Debug.Log( LayerMask.GetMask("UserLayerA", "UserLayerB") ) ;

Misalkan UserLayerAdan UserLayerBadalah lapisan kesepuluh dan kesebelas. Ini akan memiliki nilai-nilai Layer Pengguna dari 10 dan 11. Untuk mendapatkan nilai layer mask mereka nama mereka dapat diteruskan ke GetMask. Argumen dapat berupa daftar nama mereka atau array string yang menyimpan nama mereka. Dalam hal ini nilai pengembaliannya adalah 2 ^ 10 + 2 ^ 11 = 3072.

Tautan ke dokumentasi: https://docs.unity3d.com/ScriptReference/LayerMask.GetMask.html


2
Anda harus menggunakan bitwise ATAU |bukannya penambahan bilangan bulat +saat membuat penyatuan topeng, penambahan bilangan bulat mungkin menghasilkan perilaku yang tidak terduga.
Mukjizat

1
Tetapi sekali lagi, mereka bisa melakukan itu secara internal dan menyediakan metode sepertiLayerMask.NamesToLayers(params string[] layerNames)
QBrute

Poin bagus @wondra! ;) - Ya, mereka bisa melakukan QBrute ini, tetapi jauh lebih fleksibel untuk menggunakan operasi bit shiffting jika Anda ingin secara dinamis mengubah layer mask (menambahkan, menghapus lapisan, membalik, ...)
Hellium

Operasi bitwise juga sangat cepat. Mereka adalah cara terbaik untuk komposit data biner besar.
Gusdor

Ini tidak benar-benar menjawab pertanyaan mengapa metode ini tidak hanya langsung mengembalikan layer mask bukan nomor lapisan sekalipun.
Cubic
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.