开发

Unity 自定义场景管理器示例

更新时间: 2024年8月26日
在本页中,您将了解到如何使用 OVRAnchor API 直接访问场景数据并创建自己的场景管理器。

前提条件

继续学习本教程前,请完成 Unity 场景示例概览中概述的设置步骤。

该示例的工作原理

自定义场景管理器示例是单一的 Unity 场景,包含一个具有多个脚本的场景管理器 Unity 游戏对象。每个脚本都是自定义场景管理器的示例,运行示例时只应启用一个脚本。
Custom Scene Manager - Unity overview
切换场景管理器的脚本并点击编辑器中的 Play(播放),以试用每个场景管理器。快照场景管理器和动态场景管理器要求您在应用程序中启动空间设置,因此应该在设备上运行。
由于场景需要场景模型,请在运行空间设置后再试用示例。如果在查找房间锚点时没有返回任何锚点,所有脚本都包含用于请求空间设置场景捕捉的回退。

基本场景管理器

基本场景管理器是为场景数据生成 Unity 内容的最小示例。当脚本启动时,基本场景管理器会加载场景数据,并在正确位置生成随机颜色的 Unity 基元。
工作原理如下:
  1. 获取具有 OVRRoomLayout 组件的全部锚点。
  2. 为每个房间创建 Unity 游戏对象。
  3. 循环访问所有房间锚点,并通过 OVRAnchorContainer 组件获取内容。
  4. 循环访问所有子锚点并执行以下步骤。
  5. OVRLocatable 组件的启用状态设置为 true,以本地化每个锚点。
  6. 新建一个 Unity 游戏对象,并将其设置为房间的父级。使用通过 OVRSemanticLabels 组件获取的标签为该游戏对象命名。
  7. 使用 OVRLocatable.TrackingSpacePoseOVRCameraRig 上的 TrackingSpace 变换来设置变换。
  8. 如果存在 OVRBounded2D 组件,则新建一个子级 Unity 游戏对象(使用立方体基元),将变换设置为边界的尺寸,并将 MeshRenderer 材质设置为随机颜色。
  9. 如果存在 OVRBounded3D 组件,则新建一个子级 Unity 游戏对象(使用立方体基元),将变换设置为边界的尺寸,并将 MeshRenderer 材质设置为随机颜色。
  10. 如果存在 OVRTriangleMesh 组件,则新建一个子级 Unity 游戏对象(使用 Quad 基元),新建包含组件数据的 Unity 网格,更新 MeshColliderMeshRenderer 组件的 mesh,并将 MeshRenderer 材质设置为随机颜色。
生成数据后,整个过程即已完成,系统不会进一步执行任何更新。不过,追踪会移动对象,从而应用更正,所以从 OVRLocatable 更新变换是常见的操作,但基本场景管理器不会执行此操作。
Basic Scene Manager - Unity primitives spawned for Scene data

prefab 场景管理器

prefab 场景管理器扩展了基本场景管理器,以根据语义分类进行筛选,为墙壁、天花板和地板生成用户提供的 prefab,并为所有其他对象生成回退 prefab。
prefab 场景管理器与基本场景管理器的区别如下:
  • 不是生成 Unity 基元,而是生成一个用户提供的 prefab。此 prefab 仍然作为 Unity 游戏对象的父级生成,该对象通过 OVRLocatable.TrackingSpacePose 定位。
  • 确定 Unity 游戏引擎大小的逻辑在 2D 对象(墙壁、天花板和地板)和 3D 对象(全部在回退 prefab 下)之间进行切分。
  • 生成的 prefab 包含场景锚点的标签,以便用户通过头戴设备进行查看。
  • 在加载时系统会缓存所有 OVRLocatable 对象。这使得我们能够在重新置中或相机追踪空间发生变化等情况下刷新姿势,而此应用会每 5 秒钟执行一次刷新来展示这些姿势。
prefab 场景管理器尽管仍然非常简单,但与 OVRSceneManager 的核心功能非常适配。
Basic Scene Manager - user prefabs spawned for Scene data

快照场景管理器

快照场景管理器不同于静态模型,不会只加载一次数据,而会定期加载所有场景数据,从而对不同快照进行比较,并将差异记录到调试控制台。
该管理器的工作原理如下:
  1. 系统每 5 秒创建一个场景数据的快照。快照只包含 OVRAnchor 的列表。
  2. 系统通过 3 个步骤比较快照,以比较快照之间的锚点,并为新房间执行一次特殊比较。
  3. 循环访问快照 1 中的所有锚点,并检查这些锚点是否出现在快照 2 中。如果不在,则认为相关锚点已被删除或丢失
  4. 循环访问快照 2 中的所有锚点,并检查这些锚点是否出现在快照 1 中。如果不在,则认为相关锚点是新的
  5. 循环访问作为房间的所有新锚点。如果房间的任何子级出现在另一个快照中,则表示此房间已更改;否则表示此房间是新的房间。
  6. 每项更改都会记录到 Unity 的调试日志中。
快照场景管理器会采用一个动态场景模型,在此模型中,并非所有锚点在第一次查询场景数据时都可用。

动态场景管理器

动态场景管理器建立在快照场景管理器的基础上,并将所有更改与生成的 Unity 游戏对象关联,该对象可以随着场景数据的更改而更新。
该管理器的工作原理如下:
  1. 类似于快照场景管理器,动态场景管理器会定期收集场景数据的快照。快照不再只包含 OVRAnchor 列表,而是扩大为包含边界子锚点信息。
  2. 与快照场景管理器一样,系统会对锚点和房间执行快照比较,不过系统现在可以使用快照中缓存的子锚点
  3. 除了基本的比较,系统还对在上一步中被确定为已更改的房间中的所有锚点执行边界比较。
  4. 由此将得到两个快照之间所有更改的列表,并将更新应用到 Unity 对象。
  5. 对于新的对象,系统会像基本场景管理器一样生成 Unity 游戏对象。
  6. 对于已删除或缺失的对象,系统只会删除 Unity 游戏对象。
  7. 对于已更改的对象,系统会重置位置变换,并更新边界网格(如果对象上存在此类组件)。
  8. Unity 对象包含对之前快照中的 OVRAnchor 的参考。通过在快照之间查找 OVRAnchor 对,可更新此参考。
与快照场景管理器相似,动态场景管理器采用动态场景模型。动态场景管理器还支持通过 OVRSceneManager 执行重要优化,只需更新内容即可,无需是重新生成所有内容。

关键素材

基本场景管理器脚本 | .\Assets\Samples\...\Mixed Reality Sample\Scripts\CustomSceneManager | 此脚本可为场景的所有元素创建 Unity 基元。
prefab 场景管理器脚本 | .\Assets\Samples\...\Mixed Reality Sample\Scripts\CustomSceneManager | 此脚本为场景的某些元素实例化用户提供的 prefab。
快照场景管理器脚本 | .\Assets\Samples\...\Mixed Reality Sample\Scripts\CustomSceneManager | 此脚本将轮询场景数据,在每次轮询时保存快照,并将所有更改都记录到控制台。
场景管理器帮手脚本 | .\Assets\Samples\...\Mixed Reality Sample\Scripts\CustomSceneManager | 其他场景管理器脚本使用此帮手脚本来分享通用代码。
动态场景管理器脚本 | .\Assets\Samples\...\Mixed Reality Sample\Scripts\CustomSceneManager | 此脚本通过维护场景数据快照的 Unity 游戏对象关联以支持更新,扩展快照场景管理器的功能。
动态场景管理器帮手脚本 | .\Assets\Samples\...\Mixed Reality Sample\Scripts\CustomSceneManager | 动态场景管理器使用此帮手脚本来实现核心功能的易读性。