Tại sao mặt nạ lớp Unity cần sử dụng dịch chuyển bit?


9

Cuối cùng tôi đã tìm ra lý do tại sao lớp mặt nạ cho mã va chạm mặt đất của tôi không hoạt động. Tôi đã sử dụng NameToLayer()để có được lớp tôi cần, nhưng mặt nạ lớp sử dụng dịch chuyển bit để thực sự đặt giá trị mặt nạ lớp. Điều này cực kỳ bất thường và tôi không thấy bất kỳ lý do nào khiến việc này không được xử lý trong mã phía sau. Tại sao chúng ta phải sử dụng mã như thế này:

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

khi một cái gì đó như thế này:

mask = LayerMask.NameToLayer("Default");

có ý nghĩa trực quan hơn và hoạt động tương tự với phần còn lại của Unity API?


2
Sử dụng phiên bản chuỗi cần nhiều sức mạnh xử lý hơn. Chưa kể chuỗi bên trong là một mảng là kiểu tham chiếu và được thêm vào trình thu gom rác.
Krythic

Câu trả lời:


2

Điều này là cực kỳ hiệu quả. Đó là tất cả để làm điều đó - so sánh các chuỗi như ví dụ rõ ràng là chậm hơn với hệ số 10. Và các tính toán vật lý phải được tối ưu hóa rất tốt, vì vậy thật tốt khi ai đó biết những gì đang diễn ra đã viết theo cách này.

Vì vậy, câu hỏi tiếp theo rõ ràng là - tại sao điều này không được gói trong một phương thức trợ giúp để xử lý việc chuyển đổi và dịch chuyển bit. Tôi nghĩ rằng không ai thực sự có được nó - tôi đã triển khai tiện ích trợ giúp tiện lợi của riêng mình và đó là cách làm phổ biến.


1
Sự lựa chọn thiết kế chính xác của nhóm Unity sẽ là sử dụng một số nguyên làm chỉ mục, thay vì một chuỗi. Tôi co rúm người lại khi nghĩ về việc người thu gom rác có thể sẽ điên cuồng như thế nào với việc triển khai hiện tại của họ, chưa kể đến việc phân bổ mảng chuỗi.
Krythic

1
Hoàn toàn - bất kỳ mảng nào được tham chiếu tốt nhất bởi các số nguyên. Số nguyên có thể dễ dàng trở thành con người có thể đọc được bằng một enum đơn giản.
Jordan Georgiev

Việc triển khai nhanh và bẩn hoạt động, nhưng đối với các dự án lớn hơn, tôi sử dụng [Loại an toàn] ( propertystore.unity3d.com/en/#!/content353903 ).
Jordan Georgiev

19

Sử dụng dịch chuyển bit cho phép bạn tính đến nhiều lớp trong một hoạt động vật lý:

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

Nếu không dịch chuyển bit, bạn sẽ được phép chiếu sóng trong một lớp và chỉ một lớp. Trong khi với sự dịch chuyển bit, bạn có thể phát sóng trong nhiều lớp cụ thể:

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

Bạn cũng có thể chiếu sóng ở mọi lớp trừ những lớp cụ thể:

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

Nếu bạn nhìn vào "Trình quản lý lớp" trong Unity, các lớp có thể được xem là chỉ số của mảng một chiều đơn giản .


EDIT: Tôi chưa bao giờ nhìn thấy nó trước đây, nhưng LayerMasklớp có chức năng tiện ích để lấy mặt nạ lớp "được tính toán" với các tên lớp:

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

Giả sử UserLayerAUserLayerBlà lớp thứ mười và thứ mười một. Những cái này sẽ có giá trị Lớp người dùng là 10 và 11. Để có được giá trị mặt nạ lớp của chúng, tên của chúng có thể được chuyển vào GetMask. Đối số có thể là một danh sách tên của họ hoặc một chuỗi các chuỗi lưu trữ tên của họ. Trong trường hợp này, giá trị trả về sẽ là 2 ^ 10 + 2 ^ 11 = 3072.

Liên kết đến tài liệu: https://docs.unity3d.com/ScriptReference/LayerMask.GetMask.html


2
Bạn nên sử dụng bitwise OR |thay vì cộng số nguyên +khi tạo liên kết mặt nạ, phép cộng số nguyên có thể tạo ra hành vi không mong muốn.
wonderra

1
Nhưng sau đó, một lần nữa, họ có thể đã thực hiện điều đó trong nội bộ và cung cấp một phương pháp nhưLayerMask.NamesToLayers(params string[] layerNames)
QBrute

Điểm tốt @wondra! ;) - Vâng, họ đã có thể làm QBrute này, nhưng nó xa linh hoạt hơn để sử dụng bit shiffting hoạt động nếu bạn muốn tự động thay đổi layer mask (thêm, loại bỏ lớp, đảo ngược, ...)
Hellium

Hoạt động bitwise cũng cực kỳ nhanh chóng. Chúng là một cách tuyệt vời để tổng hợp dữ liệu nhị phân lớn.
Gusdor

Điều này không thực sự trả lời câu hỏi tại sao phương thức không chỉ đơn giản là trả về mặt nạ lớp thay vì số lớp.
Khối
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.