[译文] The Mixed Reality Framework in Unity

[译文] The Mixed Reality Framework in Unity

原文:https://medium.com/@stephen_hodgson/the-mixed-reality-framework-6fdb5c11feb2

当我们打造混合现实发展的未来的样子的时候,在使用Unity游戏引擎时,我们都必须努力理解和利用一组共同的概念、模式和原则,这一点很重要。在Unity引擎中编写好的软件时,最大的挑战往往是无法控制对象的生命周期和绑定到Unity的游戏循环中。

为了充分利用Unity,开发人员首先需要了解引擎的用途,并了解定义良好的软件模式和概念,以便构建健壮的框架。

MRTK正是基于该框架背后的思想构建的。

Unity's default script template

许多新手开发人员只会基于Unity提供的默认单行为模板创建新脚本,然后开始将其核心逻辑构建到这些类中。这些“Components“是为了附加到GameObjects,这些GameObjects会存在于项目的不同场景中。这里有个不好的地方是,传统的模式(如MVC或MVVM)无法在unity中开箱使用。相反,许多开发人员将应用程序逻辑与UI/UX逻辑紧密地结合在一起,这是许多专业软件工程师不赞成的做法。

A Component attached to a GameObject in a scene,如下图所示

虽然Unity预期的工作流能够很好的适用于简单的统一的项目,但是在创建更加复杂应用程序的时候,它可能会引起问题,在这些应用程序中,管理场景中运行的脚本组件的需求变得极其重要——在某些情况下至关重要。当任何时候都只应该有一个组件实例运行时,它会产生更多的问题(比如生成器或其他类似项)。为了解决这个问题,大多数开发人员都会转向Singleton模式,但是它也会引入一些问题。

The problem with Singletons in Unity

尽管批评家们普遍认为单例是一种反模式,但是许多专业人士仍然在他们的项目中使用这个概念。它的延迟初始化、跟踪全局变量和继承类(如monobhavior)的能力使Singleton模式成为管理游戏或应用程序状态的一个简单候选。然而,这种模式也伴随着它自己的一系列问题,例如在多场景项目中工作时遇到的困难:强制强化应用程序层依赖关系以及无法处理对象生命周期管理。

不像传统的软件工程,Unity无法完全控制场景中GameObject的生命周期,官方也不支持通过构造函数或自主的实例化。一切都是由游戏引擎本身直接管理的,开发者只能访问一些在游戏循环中按预定顺序执行的终身“事件函数”(例如唤醒、启动、更新等)。除此之外,引擎在每个游戏对象上调用这些事件的顺序是不确定的;没有简单的方法通知引擎如何自定义初始化组件类。这可能导致“鸡或蛋”类型的场景或比赛条件,往往难以调试。

如果开发人员,将应用程序逻辑嵌入到附加在GameObject的组件上,那么可能会出现两个问题。第一种情况是,如果GameObject disable了,那么对应的Component也会失效,第二种情况发生在单例组件在需要时或者在其他组件依赖它时没有按预期初始化的情况。

Example of a race condition for a Component that depends on a Singleton,如下图所示:

The Singleton Toolbox

在混合现实框架中,我们解决了使用传统的单例方法的问题,通过使用单例工具箱作为我们场景和引擎的游戏循环的基础,同时还提供了一种服务定位器。

作为单例的应该是应用程序,而不是单纯的组件。然后,应用程序使组件的实例可供任何特定于应用程序的代码使用。当一个应用程序使用多个这样的组件时,它可以将它们聚合到我们所称的工具箱中。

使用Singleton工具箱,整个应用程序中只有一个Singleton类类型,它负责编排所有其他运行时服务和依赖项。此脚本组件继承自MonoBehavior,因此可以将其添加到场景中的单个游戏对象,然后标记为卸载场景时不应销毁的对象。从这个单一脚本组件,所有运行时服务(例如,输入、边界、空间感知等)都注册到service locator,service locator反过来将所有Unity game循环“event function”消息转发回它们。这种编排允许对每个服务接收游戏循环消息的方式进行优先级排序和排序,从而提供对每个服务生命周期的完全控制,而不需要通过接口方法直接依赖或紧密耦合的引用。

Service Locator pattern with Event-Driven messaging,见下图:

A fusion of concepts

该框架中的一个独特而奇特的想法是我们利用和混合众所周知的编程模式和概念的方式。我们构建的主要概念是控制反转(Inversion of Control),它是使用Singleton工具箱组件中的服务定位器模式实现的。我们还通过构造器和接口契约大量合并依赖注入(Dependency Injection),以便在具体实现中实现最大的定制和灵活性。最终的结果与低层抽象层(如设备和服务)的依赖性反转原则(Dependency Inversion Principle)密切相关。低级抽象层中的所有运行时服务代码都使用普通的旧CLR对象(Plain old CLR objects),提供了模块化和易用性。

该框架还将事件驱动编程概念用于高级抽象层。这一层由带有脚本组件的游戏对象组成,这些脚本组件派生自monobhavior,通常实现某种类型的事件处理程序接口。此策略改进了框架的不同系统、开发人员的特定于应用程序的代码和Unity场景中的任何事件处理程序组件之间的通信。这个框架利用了Unity内置的事件系统,它很好地处理了这个模式的大部分实现细节。这个事件系统最初是专门设计用来处理UI/UX消息的,但是非常适合向场景中的所有游戏对象发送任何类型的事件数据。这种模式降低了使用GetComponent的成本,同时还将硬依赖性解耦到特定的具体类型。事件处理程序组件脚本不需要知道它正在侦听的服务是有效的还是活动的,因为它只关心是否通过其接口方法接收到事件。此策略与MVVM和MVC工作流非常相似,因为它确保数据通过事件处理程序接口(视图)正确地从低级抽象层(模型)流到高级抽象层。

The flow of information from the low-level to the high-level abstractions,如下图所示:

Wrapping it all up

混合现实框架中使用的体系结构被设计成正式抽象出支持跨平台开发和交付所需的所有元素。它提供了一个高度可扩展和组件化的系统,可以满足当前的所有需求,同时方便地添加任何未来的功能或需求。

该体系结构遵循良好软件工程的核心支柱:

  • 保持事物模块化,这反过来又保持项目的整洁,并使其组件专注于解决特定的问题或任务。
  • 通过接口契约和可脚本化对象,通过实现的极端定制,促进可扩展的、数据驱动的系统和功能。
  • 确保每个系统或特性都是分区和解耦的,这样整个框架就易于单独调试和测试。

The Mixed Reality Toolkit’s framework for Unity,见下图:

上图中的每一层都封装了每个系统功能的需求,定义了接口并控制了信息流。该框架确保每个系统能够独立工作,同时协作交付整个解决方案。

如果您想看到这个框架的实际应用,请获取我们最新的GitHub-Mixed Reality Toolkit for Unity。混合现实工具包确保开发人员在创建模块化、可定制和可测试的软件时具有所有优势。您的参与对我们非常重要!我们鼓励您公开问题、提供反馈和提出问题

posted @ 2021-05-26 13:06  grassofsky  阅读(84)  评论(0编辑  收藏  举报