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

1. 개요

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

빌드할 항목

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

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

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

  • 실제 평면을 감지하고 그 위에 경기장을 그립니다.
  • 카메라 뷰에서 광선을 투사하고 평면과의 교차점을 감지합니다.
  • 실제 조명 조건에 반응하여 게임에 사실감을 더합니다.

학습할 내용

  • Unity의 AR Foundation을 사용하는 프로젝트를 설정하는 방법
  • 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도 작동할 수 있지만 추가 단계가 필요할 수 있습니다. 여기에 표시된 스크린샷과 다를 수 있습니다.

새 프로젝트 만들기

Universal Render Pipeline 템플릿을 사용하여 새 프로젝트를 만듭니다. 구체적인 이름과 적절한 위치를 지정하고 만들기를 누릅니다.

필수 프레임워크 설치

Unity의 AR Foundation은 Unity Package Manager에서 찾을 수 있습니다.

  1. Window > Package Manager를 클릭하여 엽니다.

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

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

스타터 패키지 설치

이 Codelab에서는 Codelab의 일부를 빠르게 진행할 수 있는 프리팹과 스크립트가 포함된 시작 패키지를 제공하므로 AR Foundation 사용 방법에 집중할 수 있습니다.

  1. Assets > Import Package > Custom Package...를 열고 starter-package.unitypackage를 열어 스타터 패키지를 설치합니다.
  2. 팝업 창에서 모든 항목이 선택되어 있는지 확인합니다.
  3. 가져오기를 클릭합니다.

빌드 설정 변경

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

  1. File(파일) > Build Settings(빌드 설정)를 엽니다.
  2. Platform(플랫폼) 창에서 Android를 선택합니다.
  3. 선택적으로 앱이 실행되는 동안 디버깅 정보를 유지하기 위해 개발 빌드스크립트 디버깅을 사용 설정합니다.
  4. Switch Platform(플랫폼 전환)을 클릭합니다.

프로젝트 설정 변경

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

  1. Edit(수정) > Project Settings...(프로젝트 설정...)을 열고 XR Plug-in Management 섹션을 클릭합니다.
  2. Android 탭에서 ARCore를 사용 설정합니다.

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

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

필수 장면 요소 추가

유니버설 렌더 파이프라인 템플릿에는 이 튜토리얼에서 사용하지 않을 게임 오브젝트가 포함되어 있습니다.

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

  1. AR Foundation 객체를 추가합니다. 계층 구조 창에서 마우스 오른쪽 버튼을 클릭합니다. 이 메뉴를 사용하여 다음을 추가할 수 있습니다.
  • XR > AR 세션: 이 객체는 AR 환경의 수명 주기를 제어합니다.
  • XR > AR 세션 원점: 이 객체는 AR 좌표를 Unity 세계 좌표로 변환합니다.
  • Light > Directional Light: 게임 객체를 비추는 광원을 제공합니다.

계층 구조는 다음과 같아야 합니다.

  1. 계층 구조에서 만든 AR Session Origin을 펼치고 AR Camera 객체를 선택합니다. 인스펙터에서 태그를 MainCamera로 변경합니다.

렌더링 설정

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

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

  1. ForwardRenderer를 선택합니다.
  2. 인스펙터 창에서 렌더러 기능 추가를 사용하여 AR 배경 렌더러 기능을 추가합니다. 이 구성요소는 장면에서 카메라 피드를 렌더링합니다.

설정 확인

  1. 기기가 연결되어 있고 ADB 디버깅이 사용 설정되어 있는지 확인합니다.
  2. File > Build And Run...을 클릭합니다. 이렇게 하면 애플리케이션이 기기에 업로드되고 설치가 완료되면 시작됩니다.
  3. 기기 화면에 카메라 피드가 표시됩니다.

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

3. 실제 세계에서 평면 감지

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

ARPlaneManager 구성요소 추가

ARPlaneManagerARPlane를 감지하고 기기의 환경 이해가 변경되면 게임 객체를 생성, 업데이트, 삭제합니다.

  1. 계층 구조 창을 사용하여 빈 GameObject를 만듭니다.
  2. 이름을 Driving Surface Manager로 바꿉니다. 이 구성요소는 플레이어가 하나를 선택할 때까지 비행기를 표시합니다.
  3. 새 게임 객체를 선택합니다. Inspector(검사기) 창에서 Add Component(구성요소 추가)를 클릭하여 AR Plane Manager를 추가합니다.

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

스타터 패키지의 이 프리팹은 평면 장식으로 사용될 거친 바닥 텍스처를 제공합니다.

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

ARRaycastManager 구성요소 추가

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

  1. 계층 구조 창에서 Driving Surface Manager라는 객체가 선택되어 있는지 확인합니다.
  2. 인스펙터에서 구성요소 추가를 클릭하여 ARRaycastManager 구성요소를 게임 객체에 추가합니다.

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

DrivingSurfaceManager 구성요소 추가

DrivingSurfaceManagerARPlane을 선택할 수 있는 스타터 패키지의 도우미 스크립트입니다. ARPlane이 선택되면 다른 모든 평면이 숨겨지고 새 평면이 사용 중지됩니다.

  1. 계층 구조 창에서 Driving Surface Manager라는 객체가 선택되어 있는지 확인합니다.
  2. 인스펙터에서 구성요소 추가를 클릭하여 DrivingSurfaceManager 구성요소를 게임 객체에 추가합니다.

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

앱 실행

  1. File > Build And Run...을 클릭하여 변경사항을 테스트합니다.
  2. 기기를 실제 수평 표면으로 향하게 하고 기기를 움직여 ARCore가 주변 환경을 더 잘 이해하도록 합니다.

  1. ARCore가 평면을 감지하면 실제 표면을 덮는 흙 질감이 표시됩니다. ARPlaneManager는 감지된 각 비행기에 대해 지정된 Plane Prefab를 인스턴스화합니다. Driving Surface Plane 프리팹에는 지정된 ARPlane의 메시를 만드는 ARPlaneMeshVisualizer 구성요소가 있습니다.

다음 단계에서는 감지된 평면을 경기장으로 사용합니다.

4. 감지된 평면에 대해 Hit Test 실행

이전 단계에서는 평면을 감지할 수 있는 애플리케이션을 프로그래밍했습니다. 이러한 평면은 게임의 장면에 반영됩니다. 이제 감지된 평면의 표면에서 운전할 조준선과 자동차를 만들어 이러한 평면과의 상호작용을 추가합니다.

조준선 만들기

이 앱의 컨트롤 체계는 플레이어가 휴대전화를 표면에 향하게 하는 것입니다. 지정된 위치에 명확한 시각적 피드백을 제공하기 위해 조준 레티클을 사용합니다.

이 격자를 AR 평면에 '고정'하려면 히트 테스트를 사용하세요. 히트 테스트는 주어진 방향으로 광선을 투사할 때 교차점을 계산하는 기법입니다. 히트 테스트를 사용하여 카메라 뷰 방향의 교차점을 감지합니다.

레티클 추가

  1. 화면 하단의 Project 창에서 Assets > Starter Package로 이동합니다.
  2. Reticle Prefab을 프로젝트의 Hierarchy pane으로 드래그하여 장면으로 가져옵니다.
  3. 계층 구조에서 십자선을 선택합니다.
  4. 검사기에서 구성요소 추가를 클릭합니다. 시작 패키지에서 ReticleBehaviour 스크립트를 추가합니다. 이 스크립트에는 십자선을 제어하기 위한 상용구가 포함되어 있습니다.
  5. ReticleBehaviour 스크립트는 이전에 만든 Driving Surface Manager에 종속되므로 Driving Surface Manager 선택기를 클릭하여 종속 항목을 추가합니다. 장면 탭을 선택하고 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. File > Build And Run...을 클릭하여 변경사항을 테스트합니다.
  2. 기기를 평면에 대면 레티클이 카메라의 움직임을 따라야 합니다.

자동차 만들기

플레이어는 조준선 위치로 향하는 장난감 자동차를 제어합니다. 이 자동차의 모델과 동작은 스타터 패키지에 제공됩니다.

장면에 CarManager 추가

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

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

시험 운전

  1. File > Build And Run을 클릭하여 변경사항을 테스트합니다.
  2. 비행기를 탭하면 해당 위치에 작은 자동차가 표시됩니다. 이 자동차는 십자선을 따라갑니다.

게임 요소 추가

이제 플레이어가 장면에서 엔티티를 제어할 수 있으므로 플레이어가 향할 목적지를 지정합니다.

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

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

게임 테스트

  1. File > Build And Run을 클릭하여 변경사항을 테스트합니다. 2. 자동차를 만들면 패키지가 생성됩니다.
  2. 자동차를 운전하여 패키지로 이동합니다.
  3. 새로운 1개가 무작위 위치에 표시됩니다.

5. 조명 추정 설정

기본 게임이 완료되었으므로 AR 장면에 사실감을 더해 보세요. 이 단계에서는 ARCore의 조명 추정 API를 사용하여 수신되는 카메라 프레임을 기반으로 실제 환경에 있는 조명을 감지합니다. 이 정보는 실제 조명과 일치하도록 장면의 조명을 조정하는 데 사용됩니다.

조명 추정 사용 설정

  1. Hierarchy에서 AR Session Origin을 펼치고 AR Camera 객체를 선택합니다.
  2. Inspector에서 AR Camera Manager 스크립트를 펼칩니다.
  3. 조명 추정 필드를 모든 항목으로 변경합니다.

방향성 조명 수정

  1. 계층 구조에서 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. File > Build And Run을 클릭하여 변경사항을 테스트합니다.
  2. 장면의 객체를 보면 환경의 조명에 따라 색상이 지정되어 있는 것을 알 수 있습니다.
  3. 가능하다면 조명을 수정해 보세요. 예를 들어 현재 있는 방의 조명을 꺼 보세요. 객체의 조명이 실제 조명의 변화에 맞춰 조정되는 것을 확인할 수 있습니다.

6. 마무리

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

학습한 내용

  • Unity의 AR Foundation 및 Universal Rendering Pipeline을 사용하여 기본 프로젝트를 설정하는 방법
  • ARPlaneManager를 사용하여 새 요금제를 구독하는 방법
  • Raycast를 사용하여 가상 지오메트리와의 교차점을 찾는 방법
  • ARLightEstimationData을 사용하여 장면을 조명하는 방법

다음 단계

보너스 과제

여기에서 만든 게임을 확장하고 싶다면 다음 아이디어를 참고하세요.

  • PackageManager가 새 패키지를 생성할 때 TextMeshPro를 수정하여 게임에 점수 카운터를 추가합니다.
  • 성능 오버레이를 사용 설정하여 게임 실행 시 성능 정보를 확인하세요.
  • 지속적인 광선 투사를 사용하여 먼저 장면에 새 객체를 배치합니다. 해당 영역에서 평면이 감지되면 객체가 해당 평면에 스냅되도록 업데이트됩니다.