프로그래밍/Unity

Unity Layer 비트 시프트연산을 통해 제어하기

gameObject 2023. 10. 10. 11:57
728x90

유니티에서 Layer는 자주 사용됩니다.

Raycast를 사용하게 되면 Ray가 특정 대상을 맞추게 하기 위해서도 Layer설정을 자주 사용하게 됩니다.

 

이때 <<연산을 통해 특정 레이어를 설정을 해 줄 수 있습니다.

인생 유니티 ARVR교과서 책을 읽다가 << 연산을 마주했는데 어떤식으로 설정되는지 궁금하여 공부한 내용을 정리합니다.

 

* 비트연산을 굳이 사용하지 않고도 사용할 수 는 있습니다.

unity에서 자체적으로 LayerMask라는 타입을 지원하고는 있습니다.

따라서 LayerMask mask = LayerMask.GetMask("Player"); 이런식으로 마스크를 가져올 수 있습니다.

 

사용 예시와 설명 

일단 레이어에서 비트 시프트 연산을 이해하기 위해서는

레이어 하나하나가 1과 0을 나타내는 1비트라고 생각하면 편합니다.

0번부터 31번 레이어까지 볼 수 있습니다.

 

각각이 0과 1이라고 보면 되는데

해당 레이어를 활성화 시키려면 1을 주면 되고

비활성화 시키려면 0을 주면 됩니다.

 

1 << 7을 하게될 경우

1을 7칸 밀어넣겠다는 뜻이고

Player레이어를 활성화 시키겠다는 뜻이 됩니다.

 

아래 작성해 놓은 코드를 보게되면

<<(시프트 연산)

| (or 연산)

~ (not 연산)

연산자 3개를 볼 수 있고

 

해당 연산을 수행하여 RayCast를 통해

제외할 Layer와 인식시킬 Layer를 판별하고 있음을

이해할 수 있다.

 

00000000 8개 레이어라고 치면

1 << LayerMask.NameToLayer("Tower");

00100000 가 되고

1<<  LayerMask.NameToLayer("Player");

01000000 가 된다

여기에 | (or) 연산을 해주면

01100000 가 된다.

~ (not) 연산을 해주면

10011111가 되므로 내가 선택한 레이어를 제외한 나머지가

Ray에 감지된다는 의미가 된다.

 

코드

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Gun : MonoBehaviour
{
    // { 총알 관련 변수
    public Transform bulletImpact = default;
    private ParticleSystem bulletEffect = default;
    private AudioSource bulletAudio = default;
    // } 총알 관련 변수

    // 조준점(크로스헤어) 관련 변수
    public Transform crosshair = default;

    // Start is called before the first frame update
    void Start()
    {
        // 총알 효과(Effect -> FX) 파티클 시스템 컴포넌트 가져오기
        bulletEffect = bulletImpact.GetComponent<ParticleSystem>();
        // 총알 효과 오디오 소스 컴포넌트 가져오기
        bulletAudio = bulletImpact.GetComponent<AudioSource>();
    }

    // Update is called once per frame
    void Update()
    {
        // 조준점(crosshair) 표시한다.
        ARAVRInput.DrawCrosshair(crosshair);

        //사용자가 IndexTrigger 버튼을 누르면
        if (ARAVRInput.GetDown(ARAVRInput.Button.IndexTrigger))
        {
            // 총알 오디오 재생
            bulletAudio.Stop();
            bulletAudio.Play();

            //Ray를 카메라의 위치로부터 나가도록 만든다.
            Ray ray = new Ray(ARAVRInput.RHandPosition, ARAVRInput.RHandDirection);
            //Ray의 충돌 정보를 저장하기 위한 변수 지정
            RaycastHit hitInfo;
            // 플레이어 레이어 얻어오기
            int playerLayer = 1 << LayerMask.NameToLayer("Player");
            // 타워 레이어 얻어오기
            int towerLayer = 1 << LayerMask.NameToLayer("Tower");
            int layerMask = playerLayer | towerLayer;
            //Ray를 쏜다. ray가 부딪힌 정보는 hitInfo에 담긴다.
            if(Physics.Raycast(ray, out hitInfo, 200, ~layerMask))
            {
                // 총알 이펙트 진행되고 있으면 멈추고 재생
                bulletEffect.Stop();
                bulletEffect.Play();
                // 부딪힌 지점 바로 위에서 이펙트가 보이도록 설정한다.
                bulletImpact.position = hitInfo.point;
                // 부딪힌 지점의 방향으로 총알 이펙트의 방향을 설정한다.
                bulletImpact.forward = hitInfo.normal;
            }
        }
    } // Update()
}
728x90