[Unity] AR Component

Lingtea_luv·2025년 6월 5일
0

Unity

목록 보기
23/30
post-thumbnail

AR in Unity


앞서 유니티에서 AR 기반으로 개발을 하기 위한 기본 세팅 설정을 알아보았다면, 이제 오브젝트가 어떻게 제어되는지, 카메라 연동은 어떻게 이루어지는지 알아볼 필요가 있다.

AR 구성요소

AR Session

이전에도 언급한 AR Session은 하드웨어와 통신하여 센서의 데이터 수집을 담당한다. 이는 카메라에서 얻는 정보를 포함한 GPS 센서, 자이로 센서등 다양한 센서와 구성요소들의 데이터를 의미하며, 이를 바탕으로 전체적인 기능을 통제하고 담당한다.

XR Origin

XR Origin은 AR Session으로부터 수집된 데이터를 바탕으로 유니티 내의 AR 요소를 실제 환경과 일치시키는 역할을 수행한다.

현실에서 카메라가 움직이면 움직인 좌표에 대한 데이터가 XR Origin에 전달되어 하위 계층에 배치된 AR 카메라 위치에 반영된다.

여기에 여러 컴포넌트를 추가하여 AR 컨텐츠에 추가적인 기능을 구현한다.

AR Component

XR Origin에 추가할 수 있는 컴포넌트는 굉장히 다양한데, 이 중 가장 많이 활용되는 것은 AR Plane Manager와 AR Raycast Manager이다.

AR Plane Manager

AR Core는 가상의 평면을 생성하는 기능을 가지고 있는데, 이를 통해 현실 세계의 평면을 인식하는 것과 동시에 연동시켜 가상의 오브젝트와 상호작용에 사용하는 것이 가능해진다. 즉 실제 평면을 지속적으로 추적하고 이를 시각화하는 역할을 수행하는 것이다.

다만 AR Plane Manager는 현실의 평면을 인식하여 가상 평면을 생성하고 이를 추적하는 역할만 수행하기에, 해당 평면의 정보를 읽어오기 위한 기능이 추가로 필요한데 AR Raycast Manager가 그 역할을 한다.

AR Raycast Manager

PC 플랫폼 개발에서부터 정말 많이 활용한 Raycast는 정점에서 일직선으로 발사되는 레이저를 발사시켜 충돌체의 정보를 받아오는 기능이다. AR Core에서는 해당 기능을 AR Plane과 결합시켜 현실에 배치된 평면의 정보를 가져오는 기능을 지원한다.

간단히 카메라의 위치에서 카메라가 바라보는 방향으로 Ray를 쏘고 충돌한 현실 속 평면의 정보를 가져온 뒤 이를 바탕으로 가상의 평면을 생성하고, 해당 평면과 가상의 오브젝트를 상호작용 시키는 것이다.

실습

아래의 코드를 작성하고 빈 오브젝트에 넣어서 빌드를 해보자. 설치된 파일을 실행시키고 기기를 들고 돌아다니면 화면 속에 위치한 바닥에 공이 생성되고 바닥이 아닌 벽에서는 공의 위치가 변하지 않는 것을 확인할 수 있다.

이는 바닥의 정보를 통해 가상의 평면(바닥)을 생성시키고 해당 평면과 sphere가 상호작용하여 평면 위에 위치할 수 있는 것이다.

위치 정보를 계속 Update하고 있기에 떨어지지 않는 것으로 볼 수 있으나, Instantiate를 통해 새롭게 생성하더라도 떨어지지 않는 것을 확인할 수 있다.

물론 당장 카메라를 벽에 비췄을 때 sphere가 떨어지지 않는 것으로도 sphere와 plane이 상호작용하고 있다는 사실을 확인할 수 있다.

public class PrintARCamTransform : MonoBehaviour
{
    [Header("Drag&Drop")] 
    [SerializeField] private ARRaycastManager _arRaycastManager;
    [SerializeField] private Transform _sphere;

    private void Update()
    {
        CreateSphere();
    }

    public void CreateSphere()
    {
    	// 카메라의 위치에서 카메라가 바라보는 방향으로 Ray 발사
        Ray ray = new Ray(Camera.main.transform.position, Camera.main.transform.forward);
        
        // Ray와 충돌한 사물을 관리하기 위한 List
        List<ARRaycastHit> arHits = new();
        
        // Ray를 발사하고, 해당 Ray에 충돌한 사물이 평면인 경우
        if(_arRaycastManager.Raycast(ray,arHits,TrackableType.Planes))
        {
        	// 충돌체의 정보를 저장하기 위한 변수
            ARRaycastHit arHit;
            
            // 충돌체의 조건 => 평면 중 수평으로 누워있는 형태(바닥)의 충돌체
            arHit = arHits.Find(h =>(h.trackable as ARPlane).alignment == PlaneAlignment.HorizontalUp);
			
            // 충돌체가 평면이 아니거나, 평면이어도 바닥이 아닌 경우 스킵
            if (arHit == null)
            {
                return;
            }
			
            // 바닥인 경우 해당 위치로 sphere 이동
            _sphere.position = arHit.pose.position;
        }
    }
}

cf) PlaneAlignment : Horizontal Up vs Down

  • HorizontalUp : 위를 향한 수평면 (바닥, 테이블, 책상 등)
  • HorizontalDown : 아래를 향한 수평면 (천장, 선반 아래 등)
profile
뚠뚠뚠뚠

0개의 댓글