다음을 통해 공유


Unity의 로컬 앵커 전송

Azure Spatial Anchors를 사용할 수 없는 경우 로컬 앵커 전송을 통해 하나의 HoloLens 디바이스가 두 번째 HoloLens 디바이스에서 가져올 앵커를 내보낼 수 있습니다.

참고 항목

로컬 앵커 전송은 Azure Spatial Anchors보다 덜 강력한 앵커 회수를 제공하며 iOS 및 Android 디바이스는 이 접근 방식에서 지원되지 않습니다.

SpatialPerception 기능 설정

앱이 공간 앵커 를 전송하려면 SpatialPerception 기능을 사용하도록 설정해야 합니다.

SpatialPerception 기능을 사용하도록 설정하는 방법:

  1. Unity 편집기에서 "플레이어 설정" 창을 엽니다(프로젝트 설정 > 플레이어 편집>).
  2. "Windows 스토어" 탭을 클릭합니다.
  3. "게시 설정"을 확장하고 "기능" 목록에서 "SpatialPerception" 기능을 확인합니다.

참고 항목

Unity 프로젝트를 Visual Studio 솔루션으로 이미 내보낸 경우 새 폴더로 내보내거나 Visual Studio의 AppxManifest에서 이 기능을 수동으로 설정해야 합니다.

앵커 전송

네임스페이스: UnityEngine.XR.WSA.Sharing
형식: WorldAnchorTransferBatch

WorldAnchor전송하려면 전송할 앵커를 설정해야 합니다. 한 HoloLens 사용자는 자신의 환경을 검색하고 수동으로 또는 프로그래밍 방식으로 공간의 지점을 선택하여 공유 환경의 앵커가 됩니다. 그런 다음 이 지점을 나타내는 데이터를 직렬화하여 환경에서 공유하는 다른 디바이스로 전송할 수 있습니다. 그런 다음 각 디바이스는 앵커 데이터를 직렬화 해제하고 공간에서 해당 지점을 찾으려고 시도합니다. 앵커 전송이 작동하려면 각 디바이스가 앵커가 나타내는 지점을 식별할 수 있도록 충분한 환경에서 스캔해야 합니다.

설정

이 페이지의 샘플 코드에는 초기화해야 하는 몇 가지 필드가 있습니다.

  1. GameObject rootGameObject는 WorldAnchor 구성 요소가 있는 Unity의 GameObject입니다. 공유 환경의 한 사용자가 이 GameObject 를 배치하고 다른 사용자에게 데이터를 내보냅니다.
  2. WorldAnchor gameRootAnchorrootGameObject있는 UnityEngine.XR.WSA.WorldAnchor입니다.
  3. byte[] importedData 는 각 클라이언트가 네트워크를 통해 수신하는 직렬화된 앵커에 대한 바이트 배열입니다.
public GameObject rootGameObject;
private UnityEngine.XR.WSA.WorldAnchor gameRootAnchor;

void Start ()
{
    gameRootAnchor = rootGameObject.GetComponent<UnityEngine.XR.WSA.WorldAnchor>();

    if (gameRootAnchor == null)
    {
        gameRootAnchor = rootGameObject.AddComponent<UnityEngine.XR.WSA.WorldAnchor>();
    }
}

내보내기

내보내려면 WorldAnchor가 필요하고 수신 앱에 적합하도록 무엇을 호출할지 알고 있어야 합니다. 공유 환경의 한 클라이언트는 다음 단계를 수행하여 공유 앵커를 내보냅니다.

  1. WorldAnchorTransferBatch 만들기
  2. 전송할 WorldAnchors 추가
  3. 내보내기 시작
  4. 데이터를 사용할 수 있게 되면 OnExportDataAvailable 이벤트 처리
  5. OnExportComplete 이벤트 처리

전송할 내용을 캡슐화한 다음 바이트로 내보내는 WorldAnchorTransferBatch를 만듭니다.

private void ExportGameRootAnchor()
{
    WorldAnchorTransferBatch transferBatch = new WorldAnchorTransferBatch();
    transferBatch.AddWorldAnchor("gameRoot", this.gameRootAnchor);
    WorldAnchorTransferBatch.ExportAsync(transferBatch, OnExportDataAvailable, OnExportComplete);
}

데이터를 사용할 수 있게 되면 데이터 세그먼트를 사용할 수 있으므로 클라이언트 또는 버퍼에 바이트를 보내고 원하는 대로 보냅니다.

private void OnExportDataAvailable(byte[] data)
{
    TransferDataToClient(data);
}

내보내기가 완료되면 데이터를 전송하고 serialization에 실패한 경우 클라이언트에 데이터를 삭제하도록 지시합니다. serialization에 성공하면 모든 데이터가 전송되고 가져오기가 시작될 수 있음을 클라이언트에 알릴 수 있습니다.

private void OnExportComplete(SerializationCompletionReason completionReason)
{
    if (completionReason != SerializationCompletionReason.Succeeded)
    {
        SendExportFailedToClient();
    }
    else
    {
        SendExportSucceededToClient();
    }
}

가져오기

보낸 사람으로부터 모든 바이트를 받은 후에는 데이터를 WorldAnchorTransferBatch다시 가져와 루트 게임 개체를 동일한 물리적 위치에 잠글 수 있습니다. 참고: 가져오기는 때때로 일시적으로 실패하고 다시 시도해야 합니다.

// This byte array should have been updated over the network from TransferDataToClient
private byte[] importedData;
private int retryCount = 3;

private void ImportRootGameObject()
{
    WorldAnchorTransferBatch.ImportAsync(importedData, OnImportComplete);
}

private void OnImportComplete(SerializationCompletionReason completionReason, WorldAnchorTransferBatch deserializedTransferBatch)
{
    if (completionReason != SerializationCompletionReason.Succeeded)
    {
        Debug.Log("Failed to import: " + completionReason.ToString());
        if (retryCount > 0)
        {
            retryCount--;
            WorldAnchorTransferBatch.ImportAsync(importedData, OnImportComplete);
        }
        return;
    }

    this.gameRootAnchor = deserializedTransferBatch.LockObject("gameRoot", this.rootGameObject);
}

LockObject 호출을 통해 GameObject를 잠근 후에는 WorldAnchor를 사용하여 전 세계에서 동일한 물리적 위치에 유지하지만 다른 사용자와는 다른 Unity 좌표 공간의 위치에 있을 수 있습니다.