【问题标题】:Saving persistent World Anchors on HoloLens2 locally在本地保存 HoloLens2 上的持久世界锚
【发布时间】:2020-09-14 11:26:14
【问题描述】:

我目前正在开展一个房间规模的 Unity 项目,我需要使用持久的世界锚在我的设备上本地保存 GameObjects 的位置,而无需使用任何 Internet 访问或 Wifi。

我正在使用Unity 2019.4.7HoloLens2 设备。

我从早期的HoloLens1 项目以及MRTK 2.4WorldAnchorManager-Class 中遇到了一些实现,这似乎与HoloToolkit 的旧WorldAnchorManager 非常相似。 (例如:https://forums.hololens.com/discussion/2667/how-to-use-unity-world-anchors,或https://codeholo.com/2019/02/01/anchoring-your-gameobjects-in-hololens-apps

很遗憾,没有解决方案对我有用。

似乎WorldAnchors 甚至没有保存在WorldAnchorStore 中。我还尝试使用没有 WorldAnchorManager-Class 的官方 Unity WorldAnchorStore,即使它在 Unity 2020 中将被弃用。

有人可以提供一个应该在我的设置中工作的示例吗?

我也会很高兴看到每一个让锚点起作用的提示。

我当前使用WorldAnchorManager 的代码如下所示。 WorldAnchorManager-Instance 中的持久锚点已启用。

using Microsoft.MixedReality.Toolkit.Experimental.Utilities;
using UnityEngine;

public class SetWorldAnkeredObject : MonoBehaviour
{
    public GameObject anchoredObject;
    public WorldAnchorManager store;
    private string anchorId = "AnchoredCube";
    private bool savedRoot;

    void Start()
    {
        store.AttachAnchor(anchoredObject, anchorId);
    }

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.L))
        {
            store.AttachAnchor(anchoredObject, anchorId);
        }
        if (Input.GetKeyDown(KeyCode.Return))
        {
            if (anchoredObject != null)
                store.RemoveAnchor(anchorId);
            anchoredObject.transform.position = this.transform.position;
            store.AttachAnchor(anchoredObject, anchorId);
        }
    }
}

【问题讨论】:

    标签: unity3d hololens windows-mixed-reality


    【解决方案1】:

    这里有几行代码取自我的一个项目,可能对你有所帮助。

    导入

        private byte[] _importedData;
        private int _retryCount = 3;
    
        internal bool ImportAnchors()
        {
            _retryCount = 3;
            string path = GetWorldAnchorsDataPath(); // your path
            if (!File.Exists(path))
            {
                Debug.Log("Fail ImportWorldAnchors ImportAnchors File does not exist");
                return false;
            }
    
            _importedData = File.ReadAllBytes(path);
            Debug.Log("_importedData count " + _importedData.Length);
            WorldAnchorTransferBatch.ImportAsync(_importedData, OnImportComplete);
        }
    
        private void OnImportComplete(SerializationCompletionReason completionReason, WorldAnchorTransferBatch deserializedTransferBatch)
        {
            if (completionReason != SerializationCompletionReason.Succeeded)
            {
                Debug.Log("(" + _retryCount + ") Failed to import: " + completionReason.ToString());
                if (_retryCount > 0)
                {
                    _retryCount--;
                    WorldAnchorTransferBatch.ImportAsync(_importedData, OnImportComplete);
                }
                return;
            }
            Debug.Log("Success ImportWorldAnchors OnImportComplete, anchors count : " + deserializedTransferBatch.anchorCount);
            AnchorsManager.GetAndUpdateAnchorsFromBatch(deserializedTransferBatch);
    
            deserializedTransferBatch.Dispose();
        }    
    
      internal static string GetWorldAnchorsDataPath()
        {
            return Application.persistentDataPath + "/worldAnchors.dat";
        }
      
    

    出口

     internal void ExportAnchors()
        {            
            string path = GetWorldAnchorsDataPath();
            if (File.Exists(path))
            {
                FileStream fileStream = File.Open(path, FileMode.Open);
    
                /* 
                 * Set the length of filestream to 0 and flush it to the physical file.
                 *
                 * Flushing the stream is important because this ensures that
                 * the changes to the stream trickle down to the physical file.
                 * 
                 */
                fileStream.SetLength(0);
                fileStream.Close(); // This flushes the content, too.
            }
    
            WorldAnchorTransferBatch transferBatch = new WorldAnchorTransferBatch();
    
            AddAnchorsToBatch(transferBatch); // your own function to use your batch
            Debug.Log("Nb anchors in batch : " + transferBatch.anchorCount);
            WorldAnchorTransferBatch.ExportAsync(transferBatch, OnExportDataAvailable, OnExportComplete);
        }
    
        private void OnExportDataAvailable(byte[] data)
        {
            AppendAllBytes(GetWorldAnchorsDataPath(), data);    
        }
    
        private void OnExportComplete(SerializationCompletionReason completionReason)
        {
            if (completionReason != SerializationCompletionReason.Succeeded)
            {
                SendExportFailedToClient();
            }
            else
            {
                SendExportSucceededToClient();
            }
        }
    
        private void SendExportFailedToClient()
        {
            Debug.Log("Export fail");
            string path = GetWorldAnchorsDataPath();
            if (File.Exists(path))
            {
                File.Delete(path);
            }
            SuccessToExportWorldAnchors(false);
        }
    
        private void SendExportSucceededToClient()
        {
            Debug.Log("Export succeed");
            SuccessToExportWorldAnchors(true);
        }
    
    
        private static void AppendAllBytes(string path, byte[] bytes)
        {
            //argument-checking here.
    
            using (var stream = new FileStream(path, FileMode.Append))
            {
                stream.Write(bytes, 0, bytes.Length);
            }
        }
    

    【讨论】:

    • 感谢您的回复 Luckypon,我今天会检查一下并反馈这是否适合我!
    • 能告诉我如何获取holens2的路径吗?我查了一下,发现你用的是“KnownFolders.PicturesLibrary”。我可以通过 Unity 的“Application.persistentDataPath”获得路径吗?
    猜你喜欢
    • 2021-01-06
    • 1970-01-01
    • 2017-01-12
    • 1970-01-01
    • 2015-01-19
    • 2015-04-08
    • 1970-01-01
    • 2017-08-04
    • 1970-01-01
    相关资源
    最近更新 更多