佩戴HoloLens的多個用戶可以使用場景共享特性來獲取集合視野,並可以與固定在空間中某個位置的同一全息對象進行交互操作。這一切是通過空間錨共享(Anchor Sharing)來實現的。
為了使用共享服務,在AppxManifest文件中必須要啟用SpatialPerception能力。
Anchor Sharing 空間錨共享
在HoloLens掃描空間環境后,用戶可以通過手動或者編程來選擇建立一些空間錨。空間錨對象的信息的可以被序列化並傳遞給其他HoloLens設備,每一個設備都可以反序列化這些信息,並可以在空間中定位到此空間錨的位置。為了確保空間錨分享能起作用,每個設備都需要掃描周邊足夠的空間,使得空間錨代表的點能在空間中被正確識別。
Setting the SpatialPreception capability 啟用能力
上一篇空間映射的文章里提過,這里我就不重復敘述了,想起請看:http://www.cnblogs.com/mantgh/p/5626796.html
Setup 初始化
下面的示例代碼會在開始共享空間錨之前進行一些初始化操作:
public GameObject rootGameObject; private UnityEngine.VR.WSA.WorldAnchor gameRootAnchor; void Start () { gameRootAnchor = rootGameObject.GetComponent<UnityEngine.VR.WSA.WorldAnchor>(); if (gameRootAnchor == null) { gameRootAnchor = rootGameObject.AddComponent<UnityEngine.VR.WSA.WorldAnchor>(); } }
Exporting 導出
導出分享一個空間錨的操作步驟如下:
- 創建一個 WorldAnchorTransferBatch 對象
- 添加空間錨對象用以傳輸
- 開始導出數據
- 當數據可用時處理 OnExportDataAvailable事件方法
- 處理導出完成事件 OnExportComplete
WorldAnchorTransferBatch對象會將空間錨數據導出為bytes數據:
private void ExportGameRootAnchor() { WorldAnchorTransferBatch transferBatch = new WorldAnchorTransferBatch(); transferBatch.AddWorldAnchor("gameRoot", this.gameRootAnchor); WorldAnchorTransferBatch.ExportAsync(transferBatch, OnExportDataAvailable, OnExportComplete); }
當導出的數據可用時,使用任意方法將數據發往另一台設備:
private void OnExportDataAvailable(byte[] data) { TransferDataToClient(data); }
一旦數據導出完成,如果我們傳輸或者序列化數據失敗,需要告訴其他設備放棄此段錯誤的數據。如果序列化成功,需要告訴其他設備可以使用導入使用此數據:
private void OnExportComplete(SerializationCompletionReason completionReason) { if (completionReason != SerializationCompletionReason.Succeeded) { SendExportFailedToClient(); } else { SendExportSucceededToClient(); } }
Importing 導入數據
設備在接收到其他來源的數據后我們同樣可以使用WorldAnchorTransferBatch對象將我們的全息對象放置到數據代表的物理位置上。注意:導入有時會失敗,需要重試:
//這個數組需要通過網絡來從其他來源更新數據 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); }
雖然可以通過導入遠程數據來使全息對象固定在與其他用戶相同的位置上,但是全息對象在Unity坐標系中位置可能與其他人不同。
示例代碼:HoloToolkit Sharing
HoloToolkit項目簡單封裝了場景共享特性,大家可以直接使用Sharing目錄下的prefab來集成此特性。
項目主頁: https://github.com/Microsoft/HoloToolkit-Unity/tree/master/Assets/HoloToolkit/Sharing