【问题标题】:MRTK new spectator view: How to instantiate a prefab at runtime on both server and client?MRTK 新旁观者视图:如何在运行时在服务器和客户端上实例化预制件?
【发布时间】:2019-08-01 10:02:40
【问题描述】:

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

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

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

【问题讨论】:

  • 但是实例化的预制件不会相互同步。
  • 谢谢,我会调查的。

标签: hololens mrtk mr-spectatorview


【解决方案1】:

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

  1. 当在 HoloLens 的场景中声明游戏对象(标记为同步)时,它会添加一个 TransformBroadcaster 组件。这个TransformBroadcaster监控子层级变化,所以当这个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 时,它们通常会获得用于实例化镜像游戏对象组件的资产 ID。例如,当创建一个新的 MeshFilter 时,它使用assetId 通过 AssetService 查找 MeshFilter 以了解要添加到镜像游戏对象的网格:https://github.com/microsoft/MixedReality-SpectatorView/blob/73414f4429048c6f0eed154fb8bbdea93b4caa81/src/SpectatorView.Unity/Assets/SpectatorView/Scripts/StateSynchronization/NetworkedComponents/MeshFilter/MeshFilterObserver.cs#L15 这意味着动态创建网格与依赖定义的网格相比您的其中一项资产将无法正常工作。

【讨论】:

  • 谢谢,非常有用!不过,我仍然不明白的是如何处理一个复杂的游戏对象,它引用了子组件以及可能无法很好地映射到这种方法的其他方面。复杂的引用只设置一次,对象作为一个整体保存为预制件(例如,一个菜单对象,在其子项中引用了文本组件)。我不想为每个自定义脚本及其所有参数创建广播器组件,因为大多数参数在运行时不会更改,也不必同步。
  • GetOrCreateMirror 之类的方法是内部的,我没有看到主机实例化复杂对象的预制件的“官方”方式,然后这个预制件也在查看器上实例化。引用是相同的,因为它来自同一个预制件,我只需要为参数在运行时发生变化的组件编写自定义广播器。
  • GetOrCreateMirror 创建一个空游戏对象,旨在模仿宿主场景中的游戏对象。这将发生在预制件中的父游戏对象以及所有子游戏对象中,以在观众设备的场景中构建相同的游戏对象层次结构。然后 ComponentBroadcasterServices 负责在这些镜像游戏对象上重新创建您需要的组件。大多数时候,您只需要创建一些 Unity 类型(变换、网格、材质等)并将其作为组件添加到这些游戏对象中,因为它们是唯一有助于视觉上发生的事情的组件。
  • 虽然在观众设备上实例化整个预制件似乎更自然,但观众设备实际上会根据它在场景层次结构中看到的所有组件重新创建在主机设备上创建的预制件。如果其中一些组件没有正确注册,您可能需要定义自定义 ComponentBroadcasterServices。
  • 还值得一提的是,不会为您的自定义脚本创建组件广播器。然而,它将为每个具有关联 ComponentBroadcasterService 的统一类型创建。这些组件广播器可能会增加场景中 MonoBehaviours 的数量,但它们只会在评估其组件已更新时发送网络消息。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-02
  • 2013-03-09
  • 2011-10-01
相关资源
最近更新 更多