Unity의 AR Foundation을 사용하여 AR 게임 만들기

1. 개요

ARCore는 스마트폰에서 증강 현실 환경을 빌드하기 위한 Google의 프레임워크입니다. Unity의 AR Foundation을 사용하여 크로스 플랫폼 AR 애플리케이션을 빌드할 수 있습니다.

빌드할 항목

이 Codelab에서는 AR Foundation을 사용하여 간단한 게임을 빌드합니다. 이 게임의 목표는 휴대기기로 제어하는 자동차를 사용하여 소포를 수집하는 것입니다.

하지만 완전히 가상 현실에서는 이런 일이 일어나지 않습니다. 물리 원자와 디지털 비트를 혼합하여 플레이어 주변의 환경을 이해하는 게임을 만들어 새로운 유형의 플레이어 환경을 만듭니다.

이 Codelab을 마치면 게임에서 다음을 할 수 있게 됩니다.

  • 실제 비행기를 감지하고 그 위에 공터를 그립니다.
  • 카메라 뷰에서 광선을 송출하고 비행기와의 교차점을 감지합니다.
  • 실제 조명 조건에 반응하여 게임에 더욱 현실적인 느낌을 줍니다.

학습할 내용

  • Unity의 AR 기초를 사용하는 프로젝트를 설정하는 방법
  • ARPlaneManager를 사용하여 새 비행기를 구독하는 방법
  • Raycast를 사용하여 가상 도형이 있는 교차점을 찾는 방법
  • ARLightEstimationData를 사용하여 장면을 밝게 하는 방법

필요한 항목

2. 개발 환경 설정

이 단계에서는 Unity의 AR Foundation을 사용한 개발 환경을 준비합니다.

기기가 AR과 호환되는지 확인하기

Android 기기의 AR 환경은 ARCore 지원 기기에서 사용할 수 있는 ARCore를 기반으로 합니다. 개발 기기가 AR과 호환되는지 확인합니다. 또는 올바르게 구성된 AR 호환 Android Emulator 인스턴스를 사용할 수 있습니다.

기기에 USB 디버깅 설정

디버그 앱을 실행하려면 기기에서 개발자 옵션을 사용 설정해야 합니다. 아직 그렇게 하지 않았다면 개발자 옵션 및 USB 디버깅 사용 설정에 관한 Android 문서를 참고하세요.

Unity (2020.3 LTS) 설치

워크스테이션에서 Unity 2020 LTS를 설치합니다. 이 Codelab에서는 2020.3 (LTS) 버전의 Unity UI를 스크린샷으로 보여줍니다. 다른 버전의 Unity도 작동할 수 있지만 추가 단계가 필요할 수 있습니다. 여기에 표시된 스크린샷과 다르게 보일 수 있습니다.

새 프로젝트 만들기

범용 렌더링 파이프라인 템플릿을 사용하여 새 프로젝트를 만듭니다. 설명이 포함된 이름과 적절한 위치를 지정하고 만들기를 누릅니다.

필수 프레임워크 설치

Unity의 AR 기초는 Unity Package Manager에서 찾을 수 있습니다.

  1. 창 > 패키지 관리자.

  1. 이 창에서 이 Codelab에서 사용할 패키지를 설치합니다. 아이콘을 사용하여 항목을 펼쳐 이 프레임워크의 최신 버전을 확인하세요. 다음 각 프레임워크의 최신 버전을 설치합니다.
    • AR 기초
    • ARCore XR 플러그인

완료되면 패키지 관리자가 다음과 같이 표시됩니다.

시작 패키지 설치

이 Codelab에서는 AR 기초를 사용하는 방법에 집중할 수 있도록 Codelab의 일부 부분을 신속하게 처리하는 프리패브와 스크립트가 포함된 시작 패키지를 제공합니다.

  1. 애셋 > 패키지 가져오기 > Custom Package...를 실행하고 starter-package.unitypackage를 엽니다.
  2. 팝업 창에서 모든 항목이 선택되어 있는지 확인합니다.
  3. 가져오기를 클릭합니다.

빌드 설정 변경

애플리케이션이 Android에서 실행되므로 빌드 플랫폼을 Android로 변경합니다.

  1. 파일 > Build Settings(빌드 설정)를 클릭합니다.
  2. Platform 창에서 Android를 선택합니다.
  3. 원하는 경우 앱이 실행되는 동안 디버깅 정보를 유지하려면 개발 빌드스크립트 디버깅을 사용 설정합니다.
  4. Switch Platform을 클릭합니다.

프로젝트 설정 변경

시작 시 XR 시스템을 초기화하도록 AR Foundation을 구성해야 합니다.

  1. 수정 > Project Settings...를 클릭하고 XR Plug-in Management 섹션을 클릭합니다.
  2. Android 탭에서 ARCore를 사용 설정합니다.

  1. 왼쪽 창에서 Player(플레이어) 섹션을 클릭합니다.
  2. Android 탭의 기타 설정에서 그래픽 API에서 Vulkan을 삭제합니다.

  1. ARCore를 사용하는 AR 필수 앱에는 최소 API 수준 24가 필요합니다. 아래로 스크롤하여 Minimum API Level을 찾습니다. 최소 API 수준을 24로 설정합니다.

필수 장면 요소 추가

범용 렌더링 파이프라인 템플릿에는 이 튜토리얼에서 사용하지 않을 게임 객체가 함께 제공됩니다.

  1. SampleScene에서 모든 게임 객체를 삭제합니다.

  1. AR 기초 객체를 추가합니다. Hierarchy(계층 구조) 창을 마우스 오른쪽 버튼으로 클릭합니다. 이 메뉴를 사용하여 다음을 추가하세요.
  • XR > AR 세션: 이 객체는 AR 환경의 수명 주기를 제어합니다.
  • XR > AR Session Origin: 이 객체는 AR 좌표를 Unity 세계 좌표로 변환합니다.
  • 밝게 > 방향 광원: 게임 객체를 비추는 광원을 제공합니다.

계층 구조는 다음과 같습니다.

  1. 계층 구조에서 만든 AR 세션 출처를 펼치고 AR 카메라 객체를 선택합니다. 검사기에서 태그를 MainCamera로 변경합니다.

렌더링 설정

Unity의 범용 렌더링 파이프라인에서 AR Foundation과 호환되려면 한 가지 변경사항이 필요합니다.

  1. 프로젝트 창에서 애셋 > 설정으로 이동하여 ForwardRenderer 애셋을 찾습니다.

  1. ForwardRenderer를 선택합니다.
  2. Inspector 창에서 Add Renderer Feature를 사용하여 AR Background Renderer Feature를 추가합니다. 이 구성요소는 장면에서 카메라 피드를 렌더링합니다.

설정 확인

  1. 기기가 연결되어 있고 ADB 디버깅이 사용 설정되어 있는지 확인하세요.
  2. 파일 > 빌드 및 실행... 애플리케이션이 기기에 업로드되고 설치가 완료되면 시작됩니다.
  3. 기기의 화면에 카메라 피드가 표시됩니다.

다음 단계에서는 앱에 기능을 추가합니다.

3. 실제 비행기 감지

이제 기본 장면이 설정되었으므로 게임 개발을 시작할 수 있습니다. 이 단계에서는 평면을 감지하여 장면에 그립니다.

ARPlaneManager 구성요소 추가

ARPlaneManagerARPlane를 감지하고 기기의 환경 인식이 바뀌면 게임 객체를 생성, 업데이트, 삭제합니다.

  1. Hierarchy 창을 사용하여 빈 GameObject를 만듭니다.
  2. 이름을 Driving Surface Manager로 바꿉니다. 플레이어가 평면 하나를 선택할 때까지 이 구성요소는 평면을 표시합니다.
  3. 새 게임 객체를 선택합니다. Inspector 창 내에서 Add Component를 클릭하여 AR 평면 관리자를 추가합니다.

  1. Plane Prefab 필드를 설정하여 ARPlaneManager를 구성합니다.
    1. None 옆에 있는 버튼을 클릭하여 Select GameObject 창을 표시합니다.
    2. 애셋 탭을 선택하고 운전 표면 평면을 검색합니다.

스타터 패키지의 이 프리패브는 평면 장식으로 사용될 허름한 바닥 질감을 제공합니다.

  1. Detection ModeHorizontal로 변경합니다. 이렇게 하면 수평면만 제공하도록 ARPlaneManager가 구성되어 운전하기에 이상적입니다.

ARRaycastManager 구성요소 추가

ARRaycastManager는 레이캐스트 기능을 노출합니다. 다음 단계에서는 이 객체를 사용하여 사용자에게 컨트롤을 제공합니다.

  1. Hierarchy 창에서 Driving Surface Manager라는 객체가 선택되었는지 확인합니다.
  2. Inspector에서 Add Component를 클릭하여 ARRaycastManager 구성요소를 게임 객체에 추가합니다.

이 구성요소에는 추가 구성이 필요하지 않습니다.

DrivingSurfaceManager 구성요소 추가

DrivingSurfaceManagerARPlane 선택을 허용하는 스타터 패키지의 도우미 스크립트입니다. ARPlane를 선택하면 다른 모든 평면이 숨겨지고 새 비행기가 사용 중지됩니다.

  1. Hierarchy 창에서 Driving Surface Manager라는 객체가 선택되었는지 확인합니다.
  2. Inspector에서 Add Component를 클릭하여 DrivingSurfaceManager 구성요소를 게임 객체에 추가합니다.

이 구성요소에는 추가 구성이 필요하지 않습니다.

앱 실행

  1. 파일 > 빌드 및 실행...을 선택하여 변경사항을 테스트합니다.
  2. ARCore가 세상을 더 잘 이해할 수 있도록 기기를 실제 수평면을 향하게 하고 기기를 이리저리 움직여 보세요.

  1. ARCore가 평면을 감지하면 실제 표면에 먼지 질감이 표시됩니다. ARPlaneManager는 감지된 각 평면에 지정된 Plane Prefab를 인스턴스화합니다. Driving Surface Plane prefab에는 지정된 ARPlane의 메시를 만드는 ARPlaneMeshVisualizer 구성요소가 있습니다.

다음 단계에서는 감지된 평면을 플레이 필드로 사용합니다.

4. 감지된 평면에 히트 테스트 실행

이전 단계에서는 평면을 감지할 수 있는 애플리케이션을 프로그래밍했습니다. 이러한 비행기는 게임의 장면에 반영됩니다. 이제 조준 레티클과 감지된 항공기의 표면을 달리는 차량을 만들어 이러한 비행기와의 상호작용을 추가합니다.

조준 레티클 만들기

이 앱의 제어 구성표에는 플레이어가 표면을 향해 스마트폰을 가리키는 것이 포함됩니다. 지정된 위치에 대해 명확한 시각적 피드백을 제공하려면 조준 레티클을 사용합니다.

'고정' 레티클을 AR 평면에 연결하려면 히트 테스트를 사용하세요. 히트 테스트는 주어진 방향으로 광선을 캐스팅할 때 교집합을 계산하는 기술입니다. 히트 테스트를 사용하여 카메라 뷰 방향의 교차점을 감지합니다.

레티클 추가

  1. 화면 하단 근처의 프로젝트 창에서 애셋 >으로 이동합니다. 시작 패키지를 선택합니다.
  2. 레티클 프리패브를 프로젝트의 계층 구조 창으로 드래그하여 장면에 배치합니다.
  3. 계층 구조에서 레티클을 선택합니다.
  4. 검사기에서 Add Component(구성요소 추가)를 클릭합니다. 스타터 패키지에서 ReticleBehaviour 스크립트를 추가합니다. 이 스크립트에는 레티클을 제어하기 위한 상용구가 포함되어 있습니다.
  5. ReticleBehaviour 스크립트는 이전에 만든 Driving Surface Manager에 종속되므로 Driving Surface Manager 선택기를 클릭하여 종속 항목을 추가합니다. Scene(장면) 탭을 선택하고 Driving Surface Manager을 선택합니다.

ReticleBehaviour 수정

ReticleBehavior 스크립트는 기기 표시 영역의 중앙에 있는 평면에 레티클을 배치합니다.

  1. Script 필드를 더블클릭하여 ReticleBehaviour.cs 스크립트를 엽니다.
  2. 카메라의 ViewToScreenPoint를 사용하여 화면 중심을 확인합니다. Update() 메서드를 수정하여 다음을 추가합니다.
var screenCenter = Camera.main.ViewportToScreenPoint(new Vector3(0.5f, 0.5f));
  1. 이 지점을 사용하여 레이캐스트를 수행합니다. 다음을 추가합니다.
var hits = new List<ARRaycastHit>();
DrivingSurfaceManager.RaycastManager.Raycast(screenCenter, hits, TrackableType.PlaneWithinBounds);

hits 변수는 ray에 의해 교차하는 추적 가능 항목의 점을 설명하는 ARRaycastHit를 포함합니다.

  1. hits 목록을 쿼리하여 관심 있는 교차점을 확인합니다. DrivingSurfaceManager에 포함된 잠긴 영역의 우선순위를 지정하고, 해당 영역이 없는 경우 첫 번째 평면 적중을 사용합니다. Update() 끝에 다음을 추가합니다.
CurrentPlane = null;
ARRaycastHit? hit = null;
if (hits.Length > 0)
{
    // If you don't have a locked plane already...
    var lockedPlane = DrivingSurfaceManager.LockedPlane;
    hit = lockedPlane == null
        // ... use the first hit in `hits`.
        ? hits[0]
        // Otherwise use the locked plane, if it's there.
        : hits.SingleOrDefault(x => x.trackableId == lockedPlane.trackableId);
}
  1. hit에 결과가 포함된 경우 이 GameObject의 변환을 조회 위치로 이동합니다.
if (hit.HasValue)
{
    CurrentPlane = DrivingSurfaceManager.PlaneManager.GetPlane(hit.Value.trackableId);
    // Move this reticle to the location of the hit.
    transform.position = hit.Value.pose.position;
}
Child.SetActive(CurrentPlane != null);

레티클 테스트

  1. 파일 > 빌드 및 실행...을 선택하여 변경사항을 테스트합니다.
  2. 기기를 비행기에 향하게 하면 레티클이 카메라의 움직임을 따라가는 것을 확인할 수 있습니다.

자동차 만들기

플레이어가 레티클 위치를 향해 주행하는 장난감 자동차를 제어합니다. 이 자동차의 모델과 동작은 스타터 패키지에서 제공됩니다.

장면에 CarManager 추가

  1. 계층 구조에서 새로운 빈 GameObject를 만듭니다.
  2. 이름을 Car Spawner로 바꿉니다.
  3. 만든 객체를 선택합니다. Hierarchy(계층 구조) 창에서 Add Component(구성요소 추가)를 클릭하여 CarManager 구성요소를 추가합니다.
  4. 각 필드의 선택기를 클릭하여 CarManager의 종속 항목을 설정합니다.
    • 자동차 Prefab: Assets(애셋)에서 Car Prefab을 선택합니다.
    • 레티클: Scene(장면)에서 Reticle Prefab을 선택합니다.
    • Driving Surface Manager: Scene에서 Driving Surface Manager를 선택합니다.

CarManager 동작은 레티클이 있는 비행기에 장난감 자동차를 생성합니다. 원하는 경우 CarBehaviour 스크립트를 확인하여 자동차가 프로그래밍되는 방식을 알아보세요.

시험 운전

  1. 파일 > 빌드 및 실행을 클릭하여 변경사항을 테스트합니다.
  2. 비행기를 탭하면 그 위치에 작은 자동차가 표시됩니다. 이 차량은 레티클을 따라갑니다.

게임 요소 추가

이제 플레이어가 장면의 항목을 제어할 수 있으므로 플레이어에게 운전할 목적지를 제공합니다.

  1. 계층 구조에서 새로운 빈 GameObject를 만듭니다.
  2. 이름을 Package Spawner로 바꿉니다.
  3. 만든 객체를 선택합니다. Hierarchy(계층 구조) 창에서 Add Component(구성요소 추가)를 클릭하여 PackageSpawner 구성요소를 추가합니다.
  4. 각 필드의 선택기를 클릭하여 PackageSpawner의 종속 항목을 설정합니다.
    • Package Prefab: Assets(애셋)에서 Package Prefab을 선택합니다.
    • Driving Surface Manager Scene에서 Driving Surface Manager를 선택합니다.

PackageSpawner 동작은 아직 패키지가 없는 경우 잠긴 ARPlane의 임의의 위치에 새 패키지를 생성합니다.

게임 테스트

  1. 파일 > 빌드 및 실행을 클릭하여 변경사항을 테스트합니다. 2. 자동차를 만들고 나면 패키지가 생성됩니다.
  2. 차를 가지고 택배로 가져갑니다.
  3. 임의의 위치에 새 나침반이 표시됩니다.

5. 광도 추정 설정

기본 게임이 완료되었으므로 이제 AR 장면에 현실감을 더해 보세요. 이 단계에서는 ARCore의 Lighting Estimation API를 사용하여 들어오는 카메라 프레임을 기반으로 현실에 존재하는 빛을 감지합니다. 이 정보는 실제 조명에 맞게 장면의 조명을 조정하는 데 사용됩니다.

광도 추정 사용 설정

  1. Hierarchy(계층 구조)에서 AR Session Origin(AR 세션 출처)을 확장하고 AR Camera(AR 카메라) 객체를 선택합니다.
  2. Inspector(검사기)에서 AR Camera Manager(AR 카메라 관리자) 스크립트를 펼칩니다.
  3. 밝기 추정 입력란을 모든 항목으로 변경합니다.

방향 광원 수정

  1. Hierarchy(계층 구조)에서 Directional Light(방향 광원) 객체를 선택합니다.
  2. 여기에 LightEstimation 구성요소를 추가합니다. 스타터 패키지의 이 구성요소는 광원 변경을 구독하기 위한 몇 가지 상용구를 제공합니다.
  3. FrameReceived() 함수에 다음을 추가합니다.
ARLightEstimationData lightEstimation = args.lightEstimation;

if (lightEstimation.averageBrightness.HasValue)
    Light.intensity = lightEstimation.averageBrightness.Value;

if (lightEstimation.averageColorTemperature.HasValue)
    Light.colorTemperature = lightEstimation.averageColorTemperature.Value;

if (lightEstimation.colorCorrection.HasValue)
    Light.color = lightEstimation.colorCorrection.Value;

if (lightEstimation.mainLightDirection.HasValue)
    Light.transform.rotation = Quaternion.LookRotation(lightEstimation.mainLightDirection.Value);

if (lightEstimation.mainLightColor.HasValue)
    Light.color = lightEstimation.mainLightColor.Value;

if (lightEstimation.mainLightIntensityLumens.HasValue)
    Light.intensity = lightEstimation.averageMainLightBrightness.Value;

if (lightEstimation.ambientSphericalHarmonics.HasValue)
{
    RenderSettings.ambientMode = AmbientMode.Skybox;
    RenderSettings.ambientProbe = lightEstimation.ambientSphericalHarmonics.Value;
}

변경사항 테스트

  1. 파일 > 빌드 및 실행을 클릭하여 변경사항을 테스트합니다.
  2. 장면에 있는 피사체를 보면 환경의 조명에 따라 색깔이 나타나는 것을 확인할 수 있습니다.
  3. 가능하면 조명을 수정해 보세요. 예를 들어 지금 있는 방의 조명을 꺼 보세요. 물체의 빛이 실제 빛의 변화에 적응하는 것을 볼 수 있습니다.

6. 마무리

수고하셨습니다. Unity AR Foundation에 관한 Codelab을 완료했습니다.

학습한 내용

  • Unity의 AR 기초 및 범용 렌더링 파이프라인을 사용하여 기본 프로젝트를 설정하는 방법
  • ARPlaneManager를 사용하여 새 비행기를 구독하는 방법
  • Raycast를 사용하여 가상 도형이 있는 교차점을 찾는 방법
  • ARLightEstimationData를 사용하여 장면을 밝게 하는 방법

다음 단계

보너스 할당

여기에서 만든 게임을 더욱 확장하고자 한다면 다음과 같은 아이디어를 얻을 수 있습니다.

  • PackageManager가 새 패키지를 생성할 때 TextMeshPro를 수정하여 게임에 점수 카운터를 추가합니다.
  • 게임이 실행 중일 때 성능 오버레이를 사용 설정하여 성능 정보를 확인합니다.
  • 영구 Raycast를 사용하여 장면에 새 객체를 먼저 배치합니다. 해당 영역에서 평면이 감지되면 객체가 업데이트되어 해당 평면에 맞춰집니다.