레이어 마스크

sejun-Lee·2025년 5월 12일

UnityEngine

목록 보기
9/12
public class CameraRaycaster : MonoBehaviour
{
    private Camera _cam;

    [Header("Set Raycast Config")]
    [SerializeField][Range(0, 100)] private float _rayDistance = 100;
    [SerializeField] private KeyCode _actionKey = KeyCode.Mouse0;
    [SerializeField] private LayerMask _targetLayer = 0;

    private void Awake() => Init();
    private void Update() => RayShoot();

    private void Init()
    {
        _cam = Camera.main;

        //LayerUtil.AddLayer(ref _targetLayer, "Player", "Monster");
        //LayerUtil.RemoveLayer(ref _targetLayer, "Item");
    }

    private void RayShoot()
    {
        if(!Input.GetKeyDown(_actionKey)) return;

        Ray ray = _cam.ScreenPointToRay(Input.mousePosition);
        RaycastHit hit;

        if(Physics.Raycast(ray, out hit, _rayDistance, _targetLayer))
        {
            Debug.Log($"검출 대상 Layer = {_targetLayer.value}");
            Debug.Log($"오브젝트 검출 : Layer = {hit.transform.gameObject.layer}");

            // 0000 0000 _ 0000 0000 _ 0000 0000 _ 0000 0000

            // EX> Monster (9 Layer) 를 클릭해서 '제외'한다고 가정.

            // hitLayerNumber = 9
            int hitLayerNumber = hit.transform.gameObject.layer;    // 마우스로 클릭한 오브젝트 layer 번호, 자릿수

            // ...0000 0010 0000 0000
            int hitLayer = (1 << hitLayerNumber);   // 1을 왼쪽으로 hitLayerNumber 만큼 미룬다.

            // ...1111 1101 1111 1111
            int notLayer = ~hitLayer;       // ~hitLayer -> not연산자 ~, 클릭한 오브젝트를 안보이게 하기 위해

            // _cam.cullingMask =  ...1111 1111 1111 1111
            // not Layer        =  ...1111 1101 1111 1111
            // And              => ...1111 1101 1111 1111   => 둘다 1인것만 남긴다.
            _cam.cullingMask &= notLayer;
        }
    }

        // OR 연산
        // 둘중 하나라도 1이면 1
        // 중첩하고 싶은 레이어를 더할 때 쓸 수 있음.
        //
        //    ...1000 0000
        // OR ...0000 1000
        // ---------------
        // => ...1000 1000

        // NOT 연산
        // 뒤집어버림
        //
        //        ...0101 0010
        // NOT => ...1010 1101

        // AND 연산
        // 둘 다 1이어야 1이 나옴.
        // 하나라도 0이면 0이 나온다.
        //
        //     ...1010 0010
        // AND ...0010 0100
        // ---------------
        // =>  ...0010 0000
}
public static class LayerUtil
{
    public static void AddLayer(ref LayerMask target, params string[] names)
    {
        foreach(string n in names)
        {
            target |= 1 << LayerMask.NameToLayer(n);
        }
    }

    public static void RemoveLayer(ref LayerMask target, string name)
    {
        target &= ~(1 << LayerMask.NameToLayer(name));  // name으로 layer의 번호를 반환, 그리고 반전, 엔드 연산
    }
}
profile
초보 개발자

0개의 댓글