
홀로그램을 제자리에 유지하거나, 사용자와 함께 이동하거나, 경우에 따라 다른 홀로그램을 기준으로 배치하는 것은 Mixed Reality 애플리케이션을 만드는 데 큰 부분을 차지합니다. 이 문서에서는 World Locking Tools를 사용하는 권장 솔루션을 안내하지만 Unity 프로젝트에서 공간 앵커를 수동으로 설정하는 방법도 설명합니다. 코드를 시작하기 전에 Unity가 자체 엔진에서 좌표 공간 및 앵커를 처리하는 방법을 이해하는 것이 중요합니다.
세계 크기 조정 좌표계
오늘날 게임, 데이터 시각화 앱 또는 가상 현실 앱을 작성할 때 일반적인 방법은 다른 모든 좌표가 안정적으로 다시 매핑할 수 있는 하나의 절대 세계 좌표계 를 설정하는 것입니다. 이 환경에서는 항상 해당 세계의 두 개체 간의 관계를 정의하는 안정적인 변환을 찾을 수 있습니다. 이러한 개체를 이동하지 않은 경우 상대 변환은 항상 동일하게 유지됩니다. 이러한 종류의 전역 좌표계는 모든 기하 도형을 미리 알고 있는 순수 가상 세계를 렌더링할 때 쉽게 얻을 수 있습니다. 오늘날 방 규모 VR 앱은 일반적으로 바닥에 원점이 있는 이런 종류의 절대 방 규모 좌표계를 설정합니다.
반면, HoloLens와 같은 테더링되지 않은 혼합 현실 디바이스는 전 세계에 대한 동적 센서 기반 이해를 가지고 있으며, 건물 전체 층을 가로질러 여러 미터를 걸을 때 사용자의 주변 시간에 대한 지식을 지속적으로 조정합니다. 세계적 규모의 환경에서 모든 홀로그램을 순진한 강성 좌표계에 배치하면, 그 홀로그램은 세계를 기반으로 하거나 서로를 기준으로 시간이 지남에 따라 표류하게 됩니다.
예를 들어 헤드셋은 현재 전 세계 두 위치가 4미터 떨어져 있다고 생각한 다음 나중에 그 이해를 구체화하여 위치가 실제로 3.9미터 떨어져 있다는 것을 알게 될 수 있습니다. 그 홀로그램이 처음에 단일 강성 좌표계에서 4 미터 떨어져 배치된 경우, 그 중 하나는 항상 실제 세계에서 0.1 미터 떨어져 나타납니다.
사용자가 모바일일 때 물리적 세계에서 홀로그램의 위치를 유지하기 위해 Unity에 공간 앵커를 수동으로 배치할 수 있습니다. 그러나 이는 가상 세계 내에서 자체 일관성을 희생합니다. 서로 다른 앵커는 서로 간에 지속적으로 이동하며 전역 좌표 공간을 통해 이동합니다. 이 시나리오에서는 레이아웃과 같은 간단한 작업이 어려워집니다. 물리학 시뮬레이션도 문제가 될 수 있습니다.
WLT(World Locking Tools )는 사용자가 이동할 때 가상 장면 전체에 분산된 공간 앵커의 내부 공급을 사용하여 단일 강성 좌표계를 안정화하여 두 세계의 최고를 제공합니다. WLT는 카메라의 좌표와 모든 프레임의 공간 앵커를 분석합니다. WLT는 사용자의 머리 좌표에 있는 보정을 보정하기 위해 전 세계 모든 항목의 좌표를 변경하는 대신 머리의 좌표를 수정합니다.
세계 잠금 방법 선택
가능하면 홀로그램 위치 지정에 World Locking Tools를 사용합니다.
World Locking Tools 는 가상 및 실제 표식 간의 표시 불일치를 최소화하는 안정적인 좌표계를 제공합니다. World Locking Tools는 그룹의 개별 앵커를 사용하여 각 개체 그룹을 잠그지 않고 전체 장면을 공유 앵커 풀로 잠금합니다.
World Locking Tools는 공간 앵커의 내부 생성 및 관리를 자동으로 처리합니다. 홀로그램을 세계로 잠그기 위해 ARAnchorManager 또는 WorldAnchor와 상호 작용할 필요가 없습니다.
- OpenXR 또는 Windows XR 플러그 인을 사용하는 Unity 2019/2020의 경우 ARAnchorManager를 사용합니다.
- 이전 Unity 버전 또는 WSA 프로젝트의 경우 WorldAnchor를 사용합니다.
월드 잠금 설정
World Locking Tools 사용을 시작하려면 Mixed Reality 기능 도구를 다운로드합니다. 기본 사항에 대한 자세한 내용은 개요, 빠른 시작 및 기타 유용한 항목에 대한 링크는 기본 World Locking Tools 설명서 페이지를 참조하세요.
자동화된 설정
프로젝트가 준비되면 Mixed Reality > World Locking Tools에서 장면 구성 유틸리티를 실행합니다.

Important
장면 구성 유틸리티는 언제든지 다시 실행할 수 있습니다. 예를 들어 AR 대상이 레거시에서 XR SDK로 변경된 경우 다시 실행해야 합니다. 장면이 이미 제대로 구성된 경우 유틸리티를 실행해도 아무 효과가 없습니다.
시각화 도우미
초기 개발 중에 시각화 도우미를 추가하면 WLT가 제대로 설정되고 작동하는지 확인하는 데 도움이 될 수 있습니다. 프로덕션 성능이 필요하거나 어떤 이유로 더 이상 필요 없게 되면 비주얼라이저 제거 유틸리티를 사용하여 제거할 수 있습니다. 비주얼라이저에 대한 자세한 내용은 도구 설명서에서 찾을 수 있습니다.
Mixed Reality OpenXR 플러그 인은 Unity의 ARFoundation ARAnchorManager 구현을 통해 기본 앵커 기능을 제공합니다. ARFoundation의 ARAnchors에 대한 기본 사항을 알아보려면 AR 앵커 관리자용 ARFoundation Manual을 방문하세요.
네임스페이스: UnityEngine.XR.WSA
형식: WorldAnchor
주요 기술은 사용자가 얼마나 멀리 로밍했는지에 관계없이 실제 세계에서 홀로그램 클러스터를 정확하게 고정하는 공간 앵커를 만든 다음 이후 세션에서 해당 홀로그램을 다시 찾는 것입니다.
이전 Unity 버전에서는 GameObject에 WorldAnchor Unity 구성 요소를 추가하여 공간 앵커를 만듭니다.
World Anchor 추가
월드 앵커를 추가하려면 실제 세계에서 앵커하려는 변환을 사용하여 게임 개체를 호출 AddComponent<WorldAnchor>()
합니다.
WorldAnchor anchor = gameObject.AddComponent<WorldAnchor>();
이제 이 게임 개체는 실제 세계의 현재 위치에 고정됩니다. 물리적 맞춤을 보장하기 위해 시간이 지남에 따라 Unity 월드 좌표가 약간 조정되는 것을 볼 수 있습니다. 향후 앱 세션에서 이 고정된 위치를 다시 찾으려면 월드 앵커 로드를 참조하세요.
World Anchor 제거
더 이상 GameObject
물리적 세계 위치에 잠겨 있지 않고 이 프레임을 이동하지 않으려면 World Anchor 구성 요소를 호출 Destroy
합니다.
Destroy(gameObject.GetComponent<WorldAnchor>());
이 프레임을 GameObject
이동하려면 대신 호출 DestroyImmediate
합니다.
DestroyImmediate(gameObject.GetComponent<WorldAnchor>());
World Anchored GameObject 이동
월드 앵커가 있는 동안에는 이동할 GameObject
수 없습니다. 이 프레임을 GameObject
이동해야 하는 경우 다음을 수행해야 합니다.
DestroyImmediate
World Anchor 구성 요소입니다.
- 을
GameObject
이동합니다.
- 에 새 World Anchor 구성 요소를
GameObject
추가합니다.
DestroyImmediate(gameObject.GetComponent<WorldAnchor>());
gameObject.transform.position = new Vector3(0, 0, 2);
WorldAnchor anchor = gameObject.AddComponent<WorldAnchor>();
찾기 기능 변경 처리
월드 앵커는 특정 시점에 물리적 세계에서 찾을 수 없을 수도 있습니다. 그러면 Unity는 고정된 개체의 변환을 업데이트하지 않습니다. 이 상황은 앱이 실행되는 동안에도 발생할 수 있습니다. 위치 변경 사항을 처리하지 못하면 개체가 세계의 올바른 물리적 위치에 나타나지 않습니다.
위치 변경에 대한 알림을 받습니다.
이벤트를 구독합니다 OnTrackingChanged
. 이 OnTrackingChanged
이벤트는 기본 공간 앵커가 찾을 수 있거나 찾을 수 없는 상태 간에 변경될 때마다 호출됩니다.
anchor.OnTrackingChanged += Anchor_OnTrackingChanged;
이벤트를 처리합니다.
private void Anchor_OnTrackingChanged(WorldAnchor self, bool located)
{
// This simply activates/deactivates this object and all children when tracking changes
self.gameObject.SetActiveRecursively(located);
}
앵커가 즉시 isLocated
있는 경우 앵커의 속성은 반환 시로 true
AddComponent<WorldAnchor>()
설정됩니다. 따라서 OnTrackingChanged
이벤트가 트리거되지 않습니다. 더 깨끗한 패턴은 앵커를 연결한 OnTrackingChanged
후 초기 IsLocated
상태로 처리기를 호출하는 것입니다.
Anchor_OnTrackingChanged(anchor, anchor.isLocated);
영구 세계 잠금
공간 앵커는 애플리케이션 세션 간의 실제 공간에 홀로그램을 저장합니다. HoloLens 앵커 저장소에 저장되면 공간 앵커를 찾아 다른 세션에서 로드할 수 있으며 인터넷 연결이 없을 때 이상적인 대체 기능입니다.
기본적으로 World Locking Tools는 로컬 공간 앵커의 지속성을 지원하는 디바이스에서 세션 전체에서 실제 세계를 기준으로 Unity의 좌표계를 복원합니다. 애플리케이션을 종료하고 다시 실행한 후 실제 세계에서 홀로그램이 같은 위치에 표시되도록 하려면 애플리케이션이 홀로그램에 동일한 포즈를 복원하기만하면 됩니다.

애플리케이션을 더 세부적으로 제어해야 하는 경우 검사기에서 자동 저장 및 자동 로드를 사용하지 않도록 설정하고 스크립트에서 지속성을 관리할 수 있습니다. 자세한 내용은 공간 좌표계 유지를 참조 하세요.
World Locking Tools는 HoloLens 디바이스에서만 로컬 앵커 지속성을 지원합니다.
호출된 API를 XRAnchorStore
사용하면 세션 간에 앵커를 유지할 수 있습니다. 디바이스 XRAnchorStore
에 저장된 앵커의 표현입니다. Unity 장면에서 앵커를 ARAnchors
유지하거나, 스토리지에서 새 ARAnchors
앵커로 앵커를 로드하거나, 스토리지에서 앵커를 삭제할 수 있습니다.
참고 항목
이러한 앵커를 저장하고 동일한 디바이스에 로드합니다.
네임스페이스
Unity 2020 및 OpenXR의 경우:
using Microsoft.MixedReality.ARSubsystems.XRAnchorStore
또는 Unity 2019/2020 + Windows XR 플러그 인:
using UnityEngine.XR.WindowsMR.XRAnchorStore
공용 메서드
{
// A list of all persisted anchors, which can be loaded.
public IReadOnlyList<string> PersistedAnchorNames { get; }
// Clear all persisted anchors
public void Clear();
// Load a single persisted anchor by name. The ARAnchorManager will create this new anchor and report it in
// the ARAnchorManager.anchorsChanged event. The TrackableId returned here is the same TrackableId the
// ARAnchor will have when it is instantiated.
public TrackableId LoadAnchor(string name);
// Attempts to persist an existing ARAnchor with the given TrackableId to the local store. Returns true if
// the storage is successful, false otherwise.
public bool TryPersistAnchor(TrackableId id, string name);
// Removes a single persisted anchor from the anchor store. This will not affect any ARAnchors in the Unity
// scene, only the anchors in storage.
public void UnpersistAnchor(string name);
}
앵커 저장소 참조 가져오기
Unity 2020 및 OpenXR을 사용하여 XRAnchorStore를 로드하려면 ARAnchorManager의 하위 시스템인 XRAnchorSubsystem에서 확장 메서드를 사용합니다.
public static Task<XRAnchorStore> LoadAnchorStoreAsync(this XRAnchorSubsystem anchorSubsystem)
Unity 2019/2020 및 Windows XR 플러그 인을 사용하여 XRAnchorStore를 로드하려면 ARReferencePointManager/ARAnchorManager의 하위 시스템인 XRReferencePointSubsystem(Unity 2019) 또는 XRAnchorSubsystem(Unity 2020)에서 확장 메서드를 사용합니다.
// Unity 2019 + Windows XR Plugin
public static Task<XRAnchorStore> TryGetAnchorStoreAsync(this XRReferencePointSubsystem anchorSubsystem);
// Unity 2020 + Windows XR Plugin
public static Task<XRAnchorStore> TryGetAnchorStoreAsync(this XRAnchorSubsystem anchorSubsystem);
앵커 저장소 로드
Unity 2020 및 OpenXR에서 앵커 저장소를 로드하려면 다음과 같이 ARAnchorManager의 하위 시스템에 액세스합니다.
ARAnchorManager arAnchorManager = GetComponent<ARAnchorManager>();
XRAnchorStore anchorStore = await arAnchorManager.subsystem.LoadAnchorStoreAsync();
또는 Unity 2019/2020 및 Windows XR 플러그 인을 사용합니다.
// Unity 2019
ARReferencePointManager arReferencePointManager = GetComponent<ARReferencePointManager>();
XRAnchorStore anchorStore = await arReferencePointManager.subsystem.TryGetAnchorStoreAsync();
// Unity 2020
ARAnchorManager arAnchorManager = GetComponent<ARAnchorManager>();
XRAnchorStore anchorStore = await arAnchorManager.subsystem.TryGetAnchorStoreAsync();
앵커 유지/유지 취소의 전체 예제를 보려면 [Mixed Reality OpenXR 플러그 인 샘플 장면]((https://github.com/microsoft/OpenXR-Unity-MixedReality-Samples)에서 Anchors -> Anchors 샘플 GameObject 및 AnchorsSample.cs 스크립트를 확인하세요.


이전 Unity 버전 또는 WSA 프로젝트의 홀로그램 지속성의 경우 WorldAnchor를 사용합니다.
네임스페이스: UnityEngine.XR.WSA.Persistence
클래스: WorldAnchorStore
WorldAnchorStore는 홀로그램이 애플리케이션 인스턴스에서 특정 실제 위치에 유지되는 홀로그램 환경을 만듭니다. 사용자는 원하는 위치에 개별 홀로그램을 고정하고 나중에 앱 세션을 통해 동일한 위치에서 찾을 수 있습니다.
이를 WorldAnchorStore
통해 세션 간에 세계 앵커의 위치를 유지할 수 있습니다. 세션 간에 홀로그램을 유지하려면 특정 월드 앵커를 사용하는 것을 별도로 추적 GameObjects
합니다. 월드 앵커를 사용하여 루트를 GameObject
만들고 로컬 위치 오프셋을 사용하여 자식 홀로그램을 고정할 수 있습니다.
이전 세션에서 홀로그램을 로드하려면 다음을 수행합니다.
- 를 가져옵니다
WorldAnchorStore
.
- 세계 앵커의 ID를 제공하는 세계 앵커 앱 데이터를 로드합니다.
- ID로 월드 앵커를 로드합니다.
이후 세션에 대한 홀로그램을 저장하려면 다음을 수행합니다.
- 를 가져옵니다
WorldAnchorStore
.
- ID를 지정하여 월드 앵커를 저장합니다.
- ID와 함께 세계 앵커와 관련된 앱 데이터를 저장합니다.
WorldAnchorStore 가져오기
작업을 수행할 준비가 되면 알 수 있도록 참조 WorldAnchorStore
를 유지합니다. 이 호출은 비동기이므로 앱이 시작되자마자 다음을 호출할 수 있습니다.
WorldAnchorStore.GetAsync(StoreLoaded);
StoreLoaded
는 로드가 WorldAnchorStore
완료되면 처리기입니다.
private void StoreLoaded(WorldAnchorStore store)
{
this.store = store;
}
이제 특정 월드 앵커를 WorldAnchorStore
저장하고 로드하는 데 사용할 수 있는 참조가 있습니다.
세계 앵커 저장
세계 앵커를 저장하려면 세계 앵커의 이름을 지정하고 이전에 얻은 위치에 전달 WorldAnchorStore
합니다. 동일한 문자열 store.Save
에 두 개의 앵커를 저장하려고 하면 false를 반환합니다. 새 저장을 저장하기 전에 이전 저장을 삭제합니다.
private void SaveGame()
{
// Save data about holograms that this world anchor positions
if (!this.savedRoot) // Only save the root once
{
this.savedRoot = this.store.Save("rootGameObject", anchor);
Assert(this.savedRoot);
}
}
월드 앵커 로드
월드 앵커를 로드하려면 다음을 수행합니다.
private void LoadGame()
{
// Saved data about holograms that this world anchor positions:
this.savedRoot = this.store.Load("rootGameObject", rootGameObject);
if (!this.savedRoot)
{
// Game root not saved. Re-place objects or start over.
}
}
이전에 저장한 앵커를 제거하고 이전에 저장된 store.Clear()
모든 데이터를 제거하는 데 사용할 store.Delete()
수도 있습니다.
기존 앵커 열거
저장된 앵커를 나열하려면 .를 호출 GetAllIds
합니다.
string[] ids = this.store.GetAllIds();
for (int index = 0; index < ids.Length; index++)
{
Debug.Log(ids[index]);
}
다음 단계
세로로 잠긴 좌표 공간을 공유합니다.
공간 매핑에 대해 알아봅니다.
Unity 개발 검사점으로 돌아갑니다.
참고 항목