Dlaczego maski warstw Unity wymagają przesunięcia bitów?


10

W końcu zorientowałem się, dlaczego moje maski warstw dla mojego kodu kolizji z ziemią nie działają. Używałem, NameToLayer()aby uzyskać potrzebną warstwę, ale maski warstw używają przesunięcia bitowego, aby faktycznie ustawić wartość maski warstwy. Jest to niezwykle nietypowe i nie widzę żadnego powodu, dla którego nie byłoby to obsługiwane w kodzie z tyłu. Dlaczego musimy używać takiego kodu:

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

gdy coś takiego:

mask = LayerMask.NameToLayer("Default");

ma bardziej intuicyjny sens i działa podobnie do reszty interfejsu API Unity?


2
Korzystanie z wersji łańcuchowej wymaga większej mocy obliczeniowej. Nie wspominając o tym, że łańcuch jest wewnętrznie tablicą, która jest typem referencyjnym i jest dodawana do śmietnika.
— Krythic

Odpowiedzi:


3

To jest niezwykle wydajne. To wszystko - porównywanie ciągów, ponieważ oczywisty przykład jest wolniejszy dziesięciokrotnie. A obliczenia fizyki muszą być bardzo zoptymalizowane, więc dobrze, że ktoś, kto wiedział, co się dzieje, napisał to w ten sposób.

Zatem oczywistym pytaniem jest - dlaczego nie jest to zawarte w metodzie pomocniczej do obsługi konwersji i zmiany bitów. Myślę, że tak naprawdę nikt tego nie dotarł - zwinąłem swoją własną sprytną pomocniczkę i jest to powszechna praktyka.


1
Prawidłowym wyborem projektu przez zespół Unity byłoby użycie liczby całkowitej jako indeksu zamiast ciągu. Kulę się, gdy myślę o tym, jak szalony jest śmieciarz przy obecnej implementacji, nie wspominając już o przydziałach tablic łańcuchów.
— Krythic,

1
Oczywiście - każda tablica jest najlepiej przywoływana przez liczby całkowite. Liczby całkowite mogą łatwo stać się czytelne dla człowieka za pomocą prostego wyliczenia.
— Jordan Georgiev,

Szybka i brudna implementacja działa, ale do większych projektów używam [Type Safe] ( assetstore.unity3d.com/en/#!/content/35903 ).
— Jordan Georgiev,

20

Korzystanie z przesunięcia bitowego pozwala uwzględnić wiele warstw w jednej operacji fizycznej:

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

Bez przesuwania bitów, możesz raycastować w jednej warstwie i tylko w jednej. Podczas przesuwania bitów możesz raycast na wielu określonych warstwach:

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

Możesz także raycastować na wszystkich warstwach oprócz określonych:

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

Jeśli spojrzysz na „Menedżera warstw” w Unity, warstwy mogą być postrzegane jako wskaźniki prostej tablicy jednowymiarowej .


EDYCJA: Nigdy wcześniej go nie widziałem, ale LayerMaskklasa ma funkcję użyteczną do uzyskania „obliczonej” maski warstwy, biorąc pod uwagę nazwy warstw:

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

Załóżmy UserLayerAi UserLayerBsą dziesiątą i jedenastą warstwą. Będą miały wartości warstwy użytkownika 10 i 11. Aby uzyskać wartość maski warstwy, ich nazwy można przekazać do GetMask. Argumentem może być lista ich nazw lub tablica ciągów przechowujących ich nazwy. W takim przypadku zwracana wartość będzie wynosić 2 ^ 10 + 2 ^ 11 = 3072.

Link do dokumentacji: https://docs.unity3d.com/ScriptReference/LayerMask.GetMask.html


2
Podczas tworzenia unii masek powinieneś używać bitowego OR |zamiast dodawania liczb +całkowitych, dodawanie liczb całkowitych może powodować nieoczekiwane zachowanie.
— wondra

1
Ale z drugiej strony mogli to zrobić wewnętrznie i udostępnić metodę typuLayerMask.NamesToLayers(params string[] layerNames)
— QBrute,

Dobry punkt @wondra! ;) - Tak, mogliby zrobić to QBrute, ale o wiele bardziej elastyczna jest operacja przesunięcia bitów, jeśli chcesz dynamicznie zmieniać maskę warstwy (dodawanie, usuwanie warstwy, odwracanie, ...)
— Hellium

Operacje bitowe są również niezwykle szybkie. Są doskonałym sposobem na połączenie dużych danych binarnych.
— Gusdor

To tak naprawdę nie odpowiada na pytanie, dlaczego metoda nie zwraca po prostu maski warstwy zamiast numeru warstwy.
— Cubic
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.