Unity 레이어 마스크가 비트 시프 팅을 사용해야하는 이유는 무엇입니까?


10

지상 충돌 코드에 대한 레이어 마스크가 작동하지 않는 이유를 마침내 알아 냈습니다. 내가 사용하던 NameToLayer()내가 필요한 레이어를 얻을 수 있지만, 레이어 마스크는 비트 실제로 레이어 마스크 값을 설정하는 이동 사용합니다. 이것은 매우 드문 일이며 이것이 코드에서 처리되지 않는 이유는 없습니다. 왜 이런 코드를 사용해야합니까?

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

이럴 때 :

mask = LayerMask.NameToLayer("Default");

더 직관적으로 이해하고 나머지 Unity API와 유사하게 작동합니까?


2
문자열 버전을 사용하면 더 많은 처리 능력이 필요합니다. 문자열은 내부적으로 참조 유형이며 가비지 수집기에 추가되는 배열입니다.
— Krythic

답변:


3

이것은 매우 성능이 좋습니다. 이것으로 충분합니다. 명백한 예가 10만큼 느리게 문자열을 비교하는 것입니다. 물리 계산은 매우 최적화되어야하므로 진행 상황을 알고있는 사람이 이런 식으로 작성하는 것이 좋습니다.

따라서 명백한 후속 질문은-왜 이것이 변환 및 비트 시프 팅을 처리하기 위해 도우미 메소드에 포함되어 있지 않은가입니다. 나는 아무도 그것을 실제로 얻지 못했다고 생각한다. 나는 내 자신의 멋진 도우미 유틸리티를 롤업했으며 이것이 일반적인 관행이다.


1
Unity 팀이 선택한 올바른 디자인은 문자열 대신 정수를 인덱서로 사용하는 것입니다. 가비지 컬렉터가 문자열 배열 할당을 언급하지 않고 현재 구현으로 얼마나 미친 지에 대해 생각할 때 울었습니다.
— Krythic

1
절대적으로-모든 배열은 정수로 가장 잘 참조됩니다. 정수는 간단한 열거 형으로 쉽게 사람이 읽을 수 있습니다.
— Jordan Georgiev

빠르고 더러운 구현은 효과적이지만 더 큰 프로젝트에는 [Type Safe] ( assetstore.unity3d.com/en/#!/content/35903 )를 사용합니다.
— Jordan Georgiev

20

비트 이동을 사용하면 한 물리 연산에서 여러 레이어를 고려할 수 있습니다.

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

비트 시프 팅이 없으면 한 레이어에서 하나의 레이어에만 레이 캐스트 할 수 있습니다. 비트 이동을 사용하면 여러 특정 레이어에서 레이 캐스트 할 수 있습니다.

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

특정 레이어를 제외한 모든 레이어에서 레이 캐스트 할 수도 있습니다.

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

Unity 의 "Layer manager" 를 보면 레이어는 단순한 1 차원 배열의 인덱스로 볼 수 있습니다 .


편집 : 전에는 본 적이 없지만 LayerMask클래스에는 레이어 이름이 지정된 "계산 된"레이어 마스크를 가져 오는 유틸리티 함수가 있습니다.

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

가정 UserLayerA및 UserLayerB제 10 및 제 열한번째 층이다. 이것의 사용자 레이어 값은 10과 11입니다. 레이어 마스크 값을 얻기 위해 이름을 GetMask로 전달할 수 있습니다. 인수는 이름 목록이거나 이름을 저장하는 문자열 배열 일 수 있습니다. 이 경우 반환 값은 2 ^ 10 + 2 ^ 11 = 3072입니다.

설명서 링크 : https://docs.unity3d.com/ScriptReference/LayerMask.GetMask.html


2
마스크를 통합 할 때 |정수 추가 대신 비트 OR을 사용해야합니다. 정수를 추가 +하면 예기치 않은 동작이 발생할 수 있습니다.
— wondra

1
그러나 다시, 그들은 내부적으로 그렇게 할 수 있었고 다음과 같은 방법을 제공 할 수있었습니다LayerMask.NamesToLayers(params string[] layerNames)
— QBrute

좋은 점 @wondra! ;)-예,이 QBrute를 수행 할 수 있었지만 레이어 마스크를 동적으로 변경 (레이어 추가, 제거, 반전 등)하려는 경우 비트 셔팅 작업을 사용하는 것이 훨씬 더 유연합니다.
— Hellium

비트 단위 작업도 매우 빠릅니다. 큰 이진 데이터를 합성하는 훌륭한 방법입니다.
— Gusdor

이것은 실제로 왜 메소드가 레이어 번호 대신 레이어 마스크를 바로 반환하지 않는지에 대한 질문에 대답하지 않습니다.
— 큐빅
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.