HoloLens开发手记 - Unity之Persistence 场景保持
Persistence 场景保持是HoloLens全息体验的一个关键特性,当用户离开原场景中时,原场景中全息对象会保持在特定位置,当用户回到原场景时,能够准确还原原场景的全息内容。WorldAnchorStore类是实现此特性的关键API,这保证了用户能够将任何全息对象贴到任何他们想要放置的位置。
How to persist holograms across sessions 如何在整个会话中保持全息对象
WorldAnchorStore能够允许你保持场景中空间锚的位置,为了能够真正保持全息对象,你需要单独使用特定的空间锚来追踪每一个对象。通常创建一个根GameObject并附上空间锚,同时对它的子GameObject也附上具有相对位置偏移的空间锚组件。
为了从先前场景载入全息对象:
- 获取WorldAnchorStore对象
- 载入空间锚关联的应用数据,从中获取空间锚ID
- 通过ID获取空间锚对象
下个场景之前,为了保存全息对象信息:
- 获取WorldAnchorStore对象
- 指定ID来保持对应空间锚对象
- 保持与空间锚关联的应用数据
Getting the WorldAnchorStore 获取WorldAnchorStore对象
命名空间: UnityEngine.WSA.VR.Persistence
类型: WorldAnchorStore
为了能够在后续使用WorldAnchorStore,我们需要先通过异步操作打开此对象,如下:
WorldAnchorStore.GetAsync(StoreLoaded); private void StoreLoaded(WorldAnchorStore store) { this.store = store; }
现在就可以使用WorldAnchorStore对象来保存场景信息了。
Saving a WorldAnchor 保存一个空间锚
注意:同一空间锚不能多次保存。每个空间锚只应该保存一次,如果需要更新空间锚信息,则需要先删除旧的空间锚信息,然后再保存新的空间锚信息。
private void SaveGame() { // 保存空间锚对应的全息对象数据 if (!this.savedRoot) // 仅仅保存根对象一次 { this.savedRoot = this.store.Save("rootGameObject", anchor); Assert(this.savedRoot); } }
Loading a WorldAnchor 载入一个空间锚
载入空间锚数据很简单,如下:
private void LoadGame() { // Save data about holograms positioned by this world anchor this.savedRoot = this.store.Load("rootGameObject", rootGameObject); if (!this.savedRoot) { // 我们没有成功保存空间锚和全息对象数据,需要重新替换我们的对象 } }
Enumerating Existing Anchors 枚举已有的空间锚
我们可以通过枚举已保存的空间锚信息来查找之前保存的空间锚:
string[] ids = this.store.GetAllIds(); for (int index = 0; index < ids.Length; index++) { Debug.Log(ids[index]); }
示例代码
using HoloToolkit.Unity; using System.Collections.Generic; using UnityEngine; using UnityEngine.VR.WSA; using UnityEngine.VR.WSA.Persistence; public class SceneManager : Singleton<SceneManager> { private WorldAnchorStore anchorStore; private Dictionary<string, GameObject> SceneObjects = new Dictionary<string, GameObject>(); void Start() { WorldAnchorStore.GetAsync(WorldAnchorStoreLoaded); } private void WorldAnchorStoreLoaded(WorldAnchorStore store) { this.anchorStore = store; } //保存场景对象信息 public bool SaveSceneObject(string objectId, WorldAnchor anchor) { var result= this.anchorStore.Save(objectId, anchor); if (result) { SceneObjects.Add(objectId, anchor.gameObject); } return result; } //载入场景对象信息 public WorldAnchor LoadSceneObject(string objectId) { if (SceneObjects.ContainsKey(objectId)) { var target = SceneObjects[objectId]; return this.anchorStore.Load(objectId, target); } return null; } //还原场景全部内容 public void RestoreAllSceneObjects() { foreach(var key in SceneObjects.Keys) { var target = SceneObjects[key]; this.anchorStore.Load(key, target); } } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?