MRTK 新旁观者视角:如何在运行时在服务端和客户端实例化预制件?

MRTK new spectator view: How to instantiate a prefab at runtime on both server and client?

新的旁观者视图似乎改变了同步状态的方式。它不再使用 UNet,但每个组件都有一个状态同步服务。

我可以从一开始就看到它是如何同步场景中对象的变化的,但是如果我想在运行时实例化一个预制件,它是如何工作的呢?

在旧的 UNet 实现中,我将使用 NetworkManager 在所有连接的设备上对其进行实例化,并且将在所有位置创建预制件,其对子组件的所有引用都完好无损。这样做的新方法是什么?

旁观者视图的状态同步逻辑应自动评估 HoloLens/Broadcaster 设备上的游戏对象创建并将创建事件中继到 spectator/Observer 设备。旁观者视图逻辑不支持在 HoloLens 设备上重新创建在旁观者设备上创建的对象。如果这符合您的需求,逻辑流程如下:

  1. 当在 HoloLens 场景中声明一个游戏对象(标记为同步)时,它会添加一个 TransformBroadcaster 组件。这个TransformBroadcaster监听child hierarchy变化,所以当创建这个TransformBroadcaster的游戏对象的子游戏对象时,父TransformBroadcaster给子游戏对象添加一个TransformBroadcaster组件:https://github.com/microsoft/MixedReality-SpectatorView/blob/73414f4429048c6f0eed154fb8bbdea93b4caa81/src/SpectatorView.Unity/Assets/SpectatorView/Scripts/StateSynchronization/TransformBroadcaster.cs#L576

  2. 每一帧更新,TransformBroadcaster 也会观察其游戏对象的变化。如果新组件已添加到具有关联 ComponentBroadcasterServices 的游戏对象,它会将 ComponentBroadcasters 添加到游戏对象:https://github.com/microsoft/MixedReality-SpectatorView/blob/73414f4429048c6f0eed154fb8bbdea93b4caa81/src/SpectatorView.Unity/Assets/SpectatorView/Scripts/StateSynchronization/TransformBroadcaster.cs#L502

  3. 将 ComponentBroadcaster(包括 TransformBroadcaster)添加到游戏对象后,它将评估所有观察者的帧更新。如果 ComponentBroadcaster 检测到有一个观众不知道它的存在,它会向该观众发送一个广播创建事件:https://github.com/microsoft/MixedReality-SpectatorView/blob/73414f4429048c6f0eed154fb8bbdea93b4caa81/src/SpectatorView.Unity/Assets/SpectatorView/Scripts/StateSynchronization/ComponentBroadcaster.cs#L177

  4. 创建事件将被 StateSynchronizationSceneManager 中的观众设备接收。当 StateSynchronizationSceneManager 看到此创建事件时,它会获取或创建一个镜像游戏对象(本质上是 HoloLens 设备上游戏对象 运行 的副本)。然后它使用关联的 IComponentBroadcasterService 将相应的 ComponentObserver 添加到镜像游戏对象:https://github.com/microsoft/MixedReality-SpectatorView/blob/73414f4429048c6f0eed154fb8bbdea93b4caa81/src/SpectatorView.Unity/Assets/SpectatorView/Scripts/StateSynchronization/StateSynchronizationSceneManager.cs#L241

  5. 将 ComponentObserver 添加到游戏对象时,它会创建它正在观察的组件:https://github.com/microsoft/MixedReality-SpectatorView/blob/73414f4429048c6f0eed154fb8bbdea93b4caa81/src/SpectatorView.Unity/Assets/SpectatorView/Scripts/StateSynchronization/ComponentObserver.cs#L27 然后随着每次负载更新,ComponentObserver 更新这个附加组件以模仿 HoloLens 设备上显示的内容。

一旦所有 ComponentBroadcaster 都注册为使用旁观者设备创建,您应该在旁观者场景中重新创建 HoloLens 场景中新创建的游戏对象;但是,还有一些其他事情需要注意:

  1. 游戏对象需要以某种方式标记为同步候选者。这可以通过两种方式来实现。您可以通过旁观者视图设置声明场景中的所有对象都应同步:https://github.com/microsoft/MixedReality-SpectatorView/blob/master/doc/SpectatorView.Setup.md#hololens-2--hololens 或者您可以将 GameObjectHierarchyBroadcaster 添加到您的 HoloLens 场景(GameObjectHierarchyBroadcaster 组件下的所有子游戏对象将被同步)。

  2. 如果您有自定义的 Unity 类型,您可能需要创建自己的 IComponentBroadcasterService、IComponentBroadcaster 和 IComponentObserver。大多数默认的 Unity 组件(转换、网格等)已经具有组件广播服务,但您自己的自定义类型可能需要额外的工作。

  3. 您需要将相同的资产缓存编译到 HoloLens 和旁观者应用程序中。在旁观者设备上创建 ComponentBroadcaster 时,它们通常是传递给用于实例化镜像游戏对象组件的 assetId。例如,当创建一个新的 MeshFilter 时,它使用 assetId 通过 AssetService 查找 MeshFilter 以了解要将什么网格添加到镜像游戏对象:https://github.com/microsoft/MixedReality-SpectatorView/blob/73414f4429048c6f0eed154fb8bbdea93b4caa81/src/SpectatorView.Unity/Assets/SpectatorView/Scripts/StateSynchronization/NetworkedComponents/MeshFilter/MeshFilterObserver.cs#L15 这意味着动态创建网格与依赖于在您的一项资产中定义的网格将无法正常工作。