[AR Project] Scene 구성과 지면 인식 기능 구현하기

[Ted's Log] 테드로그·2021년 6월 3일
3

Project Driven Study

목록 보기
2/6
post-thumbnail

👋   Prologue

  AR 개발에 필요한 환경 설정을 모두 마쳤으니, 본격적으로 유니티 에디터를 활용해보자. 이번 포스팅에서는 디바이스의 카메라를 통해서 지면을 인식하여 그 위에 오브젝트를 배치시키는 방법에 대해서 다룰 것이다. 이 글을 읽고 따라해볼 여러분이 직접 준비할 리소스는 자신이 생성하고자 하는 오브젝트만 있으면 된다. 그럼 시작해보자!

💡   AR Session과 AR Session Origin

  AR Scene의 가장 기본적인 하이어라키 구성은 위의 이미지와 같은 모습을 띈다. 개발 환경 설정을 문제없이 마쳤다면 게임 오브젝트 추가 Window에서 XR 관련 오브젝트를 선택해서 추가할 수 있게 된다. AR Session Origin과 AR Session 오브젝트를 모두 Scene에 추가해주자.

  AR Session은 타겟 디바이스의 AR 기능 활성을 제어하는 역할을 한다. AR Session Origin은 디바이스 카메라로 추적한 요소들과의 상대적인 위치를 계산하여 유니티 Scene의 World Space로 변환시키는 역할을 수행한다. 따라서 AR Session Origin을 추가하게 되면 자식 오브젝트로 Camera 컴포넌트와 여러 스크립트가 달린 오브젝트가 추가된다. 그렇기 때문에 기본으로 존재하던 Main Camera 오브젝트는 삭제하고 다음으로 넘어가자.
(AR Session과 AR Session Origin에 대한 더 자세한 내용은 링크를 참고)

🔦   Raycast Manager와 AR Plane Manager를 통해 지면 인식하기

  AR 환경에서 지면을 인식하여 그곳에 물체를 생성시키기 위해서는 어떻게 해야 할까? 유니티 3D 환경에서는 물리 관련 라이브러리의 Raycast 함수를 통해 빛이 닿은 곳의 정보를 알 수 있었다. AR Foundation SDK도 이와 유사한 기능을 가지고 있는 AR Raycast Manager 컴포넌트를 제공한다. AR Session Origin 오브젝트에 해당 컴포넌트를 추가해서 사용하면 된다. 아래 코드블럭에 Raycast 함수의 오버로딩 목록 2가지를 적어놓았다.

public bool Raycast(
    Vector2 screenPoint, 			// 스크린 터치 지점에서 Raycast
    RaycastList<ARRaycastHit> hitResults,
    TrackableType trackableTypes = TrackableType.All)

public bool Raycast(
    Ray ray,					// 직접 생성한 Ray 객체를 통해 Raycast
    List<ARRaycastHit> hitResults,
    TrackableType trackableTypes = TrackableType.All)

  Raycast Manager와 함께 AR Plane Manager를 사용해보자. Plane Manager는 디바이스 카메라를 통해 감지한 평평한 영역위에 메쉬를 그려주어 사용자가 쉽게 인지할 수 있게 해준다. 마찬가지로 AR Session Origin에 추가해주자.

  그려줄 메쉬의 형태를 결정하기 위해서는 Plane Prefab을 인스펙터에서 연결시켜줘야 한다. GameObject - XR - AR Default Plane 오브젝트를 씬에 추가한 후, Material과 Line Render를 원하는 스타일으로 지정 후 프리팹으로 만들어 컴포넌트에 연결하자.

🗒️   스크립트 작성하기

  AR 기능이 활성화 되면 추적한 평평한 영역이 그려지고 그 곳을 사용자가 터치했을 때, 지정한 물체를 생성하고 그 후에는 평평한 영역이 더 이상 그려지기 않게 스크립트를 만들어보자. 새로운 C# 스크립트 파일을 만들고, ARTapToPlaceManager로 이름지었다.


1. namespace 설정 및 필드 선언하기

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.XR.ARFoundation;      	// AR 관련 클래스를 참조하기 위해 선언해주자
using UnityEngine.XR.ARSubsystems;		// Raycast 함수 사용 시 필요한 네임스페이스

(...)
public GameObject GameObjectToInstantiate { get; set; }  // 터치하여 생성할 오브젝트

private ARRaycastManager arRaycastManager;      // RaycastManager 참조
private ARPlaneManager arPlaneManager;		// ARPlaneManager 참조
private GameObject spawnedObject;		// 생성한 게임 오브젝트 저장할 변수 선언
private static List<ARRaycastHit> hits = new List<ARRaycastHit>();

2. 터치 좌표와, 터치 여부 결과를 반환하는 메소드 작성하기
: 사용자가 스크린을 터치 했을 때 해당 위치 정보와, bool 변수 True를 결과값으로 넘겨주는 함수를 만들어보자.
(...)
private bool TryGetTouchPostion(out Vector2 touchPositon) {
    if(Input.touchCount > 0) {
    	touchPosition = Input.GetTouch(0).position;
        return true;
    }
    touchPositon = default;
    return false;
}
(...)

3. Update 함수 작성
(...)
private void Update() {
    if (!TryGetTouchPosition(out Vector2 touchPositon)) {
        return;		// 사용자의 터치가 발생하지 않은 경우에는 업데이트 함수 실행을 더 이상 진행하지 않음 
    }
    
    // Raycast를 실행하며, 그 결과값을 hits 변수에 담아준다. 
    if (arRaycastManager.Raycast(touchPosition, hits, TrackableType.PlaneWithPolygon)) {
        var hitPose = hits[0].pose;   // ray에 맞은 결과의 첫번째 정보를 변수로 선언
        
        if (spawnedObject == null) {
            // 생성된 게임 오브젝트가 없으면 변수로 할당한 오브젝트를 생성하고 spawnObject에 담는다
            spawnedObject = Instantiate(GameObjectToInstantiate, hitPose.position, hitPose.rotation)
        }
        else {
            // 생성된 오브젝트가 있다면, hitPose 위치 정보에 맞게 위치 좌표와 회전값을 대입하여 이동시킨다.
            spawnedObject.transform.position = hitPose.position;
            spawnedObject.transform.rotation = hitPose.rotation;
            
            foreach (var plane in arPlaneManager.trackables) {
                // 오브젝트가 생성되었기 때문에 Plane 인스턴스 생성을 멈추게 한다.
                plane.gameObject.SetActive(false);
            }
        }
    }
}
(...)



👏   Epilogue

  이번 포스팅에서는 유니티 AR Scene을 구성하고, 인식한 지면 위에 물체를 위치시키기 위해 필요한 컴포넌트와 스크립트 내용에 대해 알아보았다. 다음 포스팅에서는 완성한 내용을 빌드해서 모바일 디바이스에서 직접 실행해보는 내용에 대해서 다루어보겠다.


[사진 출처 및 참고 사이트]
Unity Docs - https://docs.unity3d.com/Packages/com.unity.xr.arfoundation@4.1/manual/index.html

profile
성장하는 개발자가 되기 위한 발자취 🧑🏻‍💻

0개의 댓글