Unity Layer 비트 시프트연산을 통해 제어하기
유니티에서 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()
}