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") ) ;

가정 UserLayerAUserLayerB제 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.