티스토리 뷰
학원에서 다른 학생을 볼때
Raycast가 안 된다며 몇 시간을 붙잡고 보면
LayerMask 설정을 잘못한 경우가 꽤나 많습니다.
직접 LayerMask 변수를 만들어 사용하면 괜찮긴한데,
변수 하나 만드는 것과 Inspector에서 직접 설정 해야한다는 점이 개운하지 못합니다.
LayerMask mask = 1 << LayerMask.NameToLayer("MyLayer");
그렇다면 방법은 NameToLayer( )라는 메서드를 사용하고
비트 연산을 하는 것인데,
학원에서 배울정도면 비트 연산에 대해 낯설수 있습니다.
그것을 쉽게 해줄 방법은 아니지만,
Raycast가 어떤 int형 매개변수를
LayerMask 설정으로 사용하는 원리? 방법을 알게되면
인상깊어서 앞으로의 실수는 없지 않을까 생각해봤습니다.
using UnityEngine;
public class RaycastTest : MonoBehaviour
{
public int layerNumber = 0;
void Update()
{
if (Input.GetMouseButtonDown(0))
{
Camera cam = Camera.main;
Ray ray = cam.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out RaycastHit hit, Mathf.Infinity, layerNumber))
{
Debug.Log($"{layerNumber} : {hit.collider.name}");
}
}
}
}
어떤 테스트를 위해 간단한 스크립트를 작성했습니다.
Raycast 메서드의 Layermask 매개변수에 관한 테스트입니다.
Layermask는 특정 레이어의 오브젝트 콜라이더를 검출하기 위한 변수입니다.
만약 "UI" 라는 레이어의 오브젝트만 검출하고 싶다면
해당 레이어를 레이어마스크로 지정하면 그만일 것입니다.
LayerMask mask = 1 << LayerMask.NameToLayer("MyLayer");
보통 Raycast를 할 때 Layermask를 설정하는 방법은 위와 같습니다.
'<<' (시프트) 연산자를 사용하는 것입니다.
이 연산은 특정 레이어에 대한 비트 값을
왼쪽으로 시프트하여 LayerMask를 생성하는 방식입니다.
매개변수는 int형 값이지만,
실제로는 0과 1이라는 두 개의 숫자만을 사용하여
레이어를 '검출 대상'과 '비검출 대상'으로 구분하기 위해
이진수를 사용하는 것입니다.
따라서 '1 <<' 연산은 2의 제곱수를 사용하는 것과 같습니다.
예를 들어, '1 << 3'은 이진수 1000, 즉 2^3의 값을 의미합니다.
Layer 설정에서 Layer 번호를 확인합니다.
Default Layer는 0번입니다. 2의 0제곱으로 Layermask 번호를 int로 바꾸면 1입니다.
TransparentFX Layer는 1번입니다. 2의 1제곱으로 int로는 2입니다.
다른 Layer도 마찬가지입니다.
1
2
4
8 (Layer 3은 정의 되어있지 않음)
16
32
64 ...
이런 식으로 오브젝트마다 Layer를 할당해주고,
처음의 스크립트를 사용하여 Raycast를 실행합니다.
Physics.Raycast(ray, out RaycastHit hit, Mathf.Infinity, layerNumber)
int형 변수 Layer Number를 Raycast의 매개변수로 사용하면서 말입니다.
우측 상단의 숫자를 눈여겨 보면
오브젝트의 순서대로 1, 2, 4, 16, 32, 64 일때
해당 오브젝트가 Raycast에 검출되는 것을 볼 수 있습니다.
특히 Layer Number가 3일 경우
1번과 2번의 오브젝트 모두가 검출 되는 것을 볼 수 있는데,
3은 이진수로 0000 0011인 점에서
이진수로 0000 0001인 1과 0000 0010인 2를 모두 포함하는 것입니다.
LayerMask mask = 1 << LayerMask.NameToLayer("MyLayer");
이러한 사정을 알고 LayerMask를 설정한다면
NamToLayer 메서드 대신 int값을 사용하여 사용할 수도 있겠다 생각했습니다.
권장하지 않는 방법이지만,
and 연산자나 or 연산자에 약하면 한 번은 써볼 수 있을 것 같습니다;;
ex) 1+2 = 3 (0번 레이어와 1번 레이어만 검출한다)
int mask = (1 << 0) | (1 << 1); // 0번과 1번 레이어만 검출
ex) 1+4+32 = 37 (0번 레이어와 2번 레이어, 5번 레이어만 검출한다...)
int mask = (1 << 0) | (1 << 2) | (1 << 5);
'유니티' 카테고리의 다른 글
Scroll View에 대한 사용법 정리 (0) | 2024.10.15 |
---|---|
마우스 드래그로 원형 UI 선택 (0) | 2024.06.09 |
UI버튼의투명영역이감지되지않게하고싶다 (0) | 2020.07.09 |