暂留技巧

暂留在基础平台支持的情况下可用。 目前,这仅限于使用 Unity 的内置 VR 支持(旧式 XR)的 HoloLens 系列设备。

基本暂留

World Locking Tools 的基本暂留默认启用。 该启用分为两部分。

持久性检查器设置

此处的相关复选框是“自动加载”和“自动保存”,它们已被选中。 你可能会注意到它们已灰显。这是因为它们是“使用默认值”选项的一部分。 禁用“使用默认值”后,可以选择自动化选项的任意组合。

可以进一步阅读这些设置,以及通过脚本操纵它们

自动保存

AutoSave 选项指示 WLT 在运行应用程序时进行频繁和定期的状态保存。 应用程序可以随时终止,其状态损失最小。

AutoLoad

AutoLoad 选项指示 WLT 在启动时加载任何以前保存的状态。 这实际上允许应用程序从上次会话中断的地方恢复一个新会话(w.r.t. WLT)。

完全暂留

启用 AutoSave 和 AutoLoad 后,WLT 可以跨会话无缝运行。 虽然全局空间的位置和方向在第一次运行时是任意的(因为没有保存之前的状态,所以它在启动时使用头部姿势作为原点),后续运行将使用同一坐标系。

当应用程序在与前一个会话空间断开连接的空间中启动一个新会话时,这会导致有趣的行为。 有关详细信息,请参阅下面的按位置暂留部分。

注意

AutoSave 和 AutoLoad 设置也适用于全局 SpacePin。 有关详细信息,请参阅以下内容

应用程序对暂留的控制

默认的完全暂留适用于各种应用程序。

但是,一些应用程序可能想要更精细地控制该过程。

将启用 WLT 自动暂留分为两个属性(即 AutoSave 和 AutoLoad),这似乎有点奇怪。 检查两者独立使用的案例可能会提供对整个暂留系统的见解。

AutoSave 而非 AutoLoad

自动保存但应用程序控制加载的设置

使用此配置,WLT 设置为定期保存其状态。 但是,它不会在启动时自动加载任何暂留的状态。

相反,系统将以一种全新的状态启动,就好像它是第一次在此设备上运行一样。 只有在对 Load() 进行显式请求之后,它才会还原先前会话的状态。

这样,应用程序就可以决定是否适合还原以前的会话状态,也可在必要时修改要还原的数据。

常规 WLT 保存状态位于文件“LocalState/frozenWorldState.hkfw”中。 由 WLT 创建文件后,该文件可以复制到另一个位置并由应用程序自行决定还原。

对齐 (SpacePin) 数据的保存文件默认为“LocalState/Persistence/Alignment.fwb”。 但是,应用程序可以通过对齐管理器的 SaveFileName 替代该文件。

需要在启动时决定使用此配置加载先前会话的状态。 运行先前会话的保存状态后,该状态将被此会话的状态替代。 如需更灵活的设置,请参阅下面的手动保存和加载

手动保存而非 AutoLoad

设置自动加载,但应用程序控制保存

在此配置中,WLT 将在启动时从先前会话加载任何可用状态。 但是,它不会自动保存状态。 这样,应用程序就可以通过调用 Save() 来决定是否以及何时需要保存状态。

AutoLoad 仅命令 WLT 在启动时加载任何可用状态。 应用程序可以通过显式调用 Load() 按需还原任何已保存的状态。

手动保存和加载

没有持久性或应用程序控制的持久性的设置

应用程序可以选择保持对保存和加载过程进行完全控制。

然后,将仅通过应用程序对 Save() 的显式调用来保存状态,并且仅通过对 Load() 的显式调用进行加载。

通过调用 Load() 加载的状态可能已在此会话的较早时间或先前会话中保存。

禁用暂留

如上所述,应用程序始终可以通过脚本实现暂留。 可以通过脚本或 Inspector 中的 WorldLockingContext 来启用和禁用自动暂留。 如果禁用了自动暂留,WLT 将不会在没有来自应用程序的显式请求的情况下尝试保存或加载状态。

当然,由于 AutoLoad 指令只影响在启动时是否进行加载,因此在启动后更改脚本中的值不起作用。

开发过程中的注意事项

如上所述,全局 WLT 和对齐的保存文件的位置对于应用程序来说是全局的。 特别是,对齐节点(也称为 SpacePin)按名称暂留(见下文)。 如果应用程序使用来自一个场景的一组 SpacePin 保存状态,然后使用来自另一个场景的一组 SpacePin 加载状态,并且两组 SpacePin 具有相同的名称,那么行为是未定义的。

可以通过多种方法来解决此问题。 如果可能的话,最好避免在项目中重用 SpacePin 名称。 如果在重新部署后,你看到了意外的场景滑动行为,请尝试删除 WLT 保存状态。 同样,在彻底更改应用程序时,过于谨慎的人可能会想要从设备中删除其 WLT 保存文件,或者只是在安装新版本之前卸载应用程序。

按位置暂留

场景

一类有趣的应用程序可在多个物理位置上运行。 应用程序可能在 A 房间中运行,在设备关闭后重新定位,然后该应用程序在 B 房间中重新启动。B 房间可能在 A 房间的楼下,也可能在另一个大陆上。 应用程序和设备对此并不知情。

为简单起见,假设应用程序配置为手动 WLT 暂留。

演练

请考虑这些互不相连的房间 A 和 B。

不同大洲的空房间

应用程序在 A 房间中启动。在该房间内建立一个连续的冻结坐标空间后,整个房间将映射到片段 1。 一个持久保存的全息影像物体 X 被放置在该房间中。 然后,应用程序保存状态并退出。

世界锁定室 A.

设备关机后进入 B 房间,然后重新启动。

由于设备识别出这不是 A 房间,因此 WLT 为其内容分配一个新的片段 ID,例如 ID == 29。 为什么是 29? 因为它不是 1。 片段 ID 的值是任意的,但一个片段的 ID 不会是 FragmentId.Invalid 或 FragmentId.Unknown,也不会与任何其他已知片段相同。

世界锁定室 B 与房间 A 未跟踪

现在有两个片段,但无法将其合并(因为没有关于它们相对位置的信息)。

感兴趣的应用开发人员可能会问:我在 A 房间中放置了一个持久保存的物体 X,当应用程序在 B 房间启动时,加载物体 X 会发生什么情况?

答案是,行为由应用程序开发人员决定。 当将物体 X 放置在 A 房间中时,当前片段 ID 可用,并且可以持久保存。 然后,应用程序可以在启动时根据当前片段是否与创建时相同来决定是否显示物体 X。

在这里,开发人员决定(并实现)仅在当前片段 ID 为 1 时加载物体 X,而仅在当前片段为 29 时加载来自 B 房间的物体 Y。

与空间关联的片段 ID 的暂留被保存为 World Locking Tools 的暂留的一部分。 但是,与物体关联的片段 ID 的暂留以及基于其所要执行的操作都取决于应用程序。

除了物体的相关片段 ID 外,还可以保存其在全局空间中的姿势。 如果片段 ID 匹配,则在加载物体后,可以还原其姿势,将其返回到上次会话期间在物理世界中的位置。 有了 World Locking Tools 暂留,相对于周围的物理世界特性,姿势在会话之间保持不变。

SpacePin 的暂留

可以将 SpacePin 看作是 AlignmentAnchor 的应用程序端包装器。 SpacePin(和派生类)是 Unity 组件,而 AlignmentAnchor 是纯概念性组件;没有与 AlignmentAnchor 对应的类或类型。 因此,在本讨论中,SpacePin 和 AlignmentAnchor 将互换使用,一般首选 SpacePin。

不过,如果 AlignmentManager 没有 SpacePin 的概念,但它可以保留 SpacePin,这可能会让人感到不解。 这是因为 AlignmentManager 管理概念性 AlignmentAnchor,它体现了 SpacePin 的本质,并且可以通过它重构 SpacePin。

与一般的 WLT 暂留系统相比,SpacePin 的暂留有更多的应用程序级别控制,因为与 World Locking Tools 的其他部分相比,SpacePin 本质上更多地由应用程序输入驱动。

务必记住 SpacePin(和 AlignmentAnchor)是按名称持久保存的。 该要求比一般要求稍多,即同一 IAlignmentManager 中没有两个活动的 SpacePin 具有相同的名称。 如果持久保存 SpacePin,那么同一个数据库中的任何两个 SpacePin 都不能具有相同的名称,无论其是否处于活动状态。

对齐管理器数据库

每个 IAlignmentManager 都有一个按名称命名的 SpacePin 数据库,正如其实现 RestoreAlignmentAnchor(string uniqueName, Pose virtualPose) 所暗示的那样。

全局对齐数据库

WorldLockingManager.GetInstance() 拥有一个全局 IAlignmentManager。 如前所述,其默认保存文件位置由 SaveFileName 属性确定。 请注意,SaveFileName 是类 AlignmentManager(而不是接口 IAlignmentManager)的属性。 IAlignmentManager 实现可以在没有任何文件或文件名的概念的情况下实现暂留。 SaveFileName 是 AlignmentManager 实现暂留的方式的产物,因此仅限于 AlignmentManager。

本地对齐数据库

可以有任意数量的子空间对齐管理器,其中每个 AlignSubtree 对应一个子空间对齐管理器,并以字段 AlignSubtree.alignmentManager 的形式出现。 此外,应用程序可创建自己的 AlignmentManager 实例,也可创建从 IAlignmentManager 派生的自己的类。

每个 AlignSubtree 组件的 AlignmentManager 都有自己的保存文件位置,默认为 GameObject 的名称,其扩展名为“.fwb”。 例如,如果 AlignSubtree 组件位于名为“MyRoot”的 GameObject 上,则保存文件将命名为“MyRoot.fwb”。 可以使用正斜杠“/”将其放在子文件夹中。 如果两个 AlignSubtree 组件使用同一保存文件位置,可能会出现错误。

但实际上并非如此

强烈建议这样做,从长远来看,为 SpacePins/AlignmentAnchors 提供全局唯一名称比尝试管理较轻的本地唯一要求更简单、更可靠。 请根据自己的需要这样做。

另请参阅