在您的 Unity 项目中实施常见的游戏编程设计模式可以帮助您高效地构建和维护一个简洁、有序和可读的代码库。设计模式减少了重构和测试时间,加快了开发进程,为游戏、团队和业务的发展奠定了坚实的基础。
不要把设计模式看成是可以复制并粘贴到代码中的成品解决方案,而应把它看成是可以帮助你构建更大的、可扩展的应用程序的额外工具。
本页介绍模型视图控制器 (MVC) 和模型视图演示器 (MVP) 设计模式。
这里的内容基于免费电子书、 用游戏编程模式提升代码水平.
在Unity 最佳实践中心或通过这些链接查看Unity游戏编程设计模式系列中的更多文章:
您可以使用模型视图控制器(MVC)和模型视图演示器(MVP)设计模式,将应用程序中的数据和逻辑与呈现方式分开。这些模式应用了 "关注点分离 "原则,可以提高代码库的灵活性和可维护性。
在 Unity 游戏开发中,您可以使用这些模式将游戏逻辑分离成不同的组件,如数据(模型)、可视化表示(视图)以及控制两者之间交互的逻辑(控制器或演示器)。
MVC 是一系列设计模式,通常用于开发软件应用程序的用户界面。
MVC 背后的总体思想是将软件的逻辑部分与数据和表现形式分开。这有助于减少不必要的依赖关系,并有可能减少细枝末节的代码。
顾名思义,MVC 模式将应用程序分为三层:
模型存储数据: 严格来说,模型是一个容纳值的数据容器。它不执行游戏逻辑或运行计算。
视图是界面: 视图 "可在屏幕上格式化和渲染数据的图形显示。
控制器处理逻辑: 把它想象成大脑。它处理游戏数据,并计算运行时数值的变化情况。
这种关注点的分离还具体界定了这三个部分之间的互动方式。模型管理应用程序数据,而视图则向用户显示这些数据。控制器负责处理输入,并对游戏数据进行决策或计算。然后将结果发回模型。
控制器本身不包含任何游戏数据。景观》也没有。MVC 设计限制了每一层的功能。一部分保存数据,另一部分处理数据,最后一部分向用户显示数据。
从表面上看,这可以看作是单一责任原则的延伸。每个部分只做一件事,而且做得很好,这就是 MVC 架构的主要优势。
使用 MVC 开发 Unity 项目时,现有的 UI 框架(UI 工具包或Unity UI)自然会作为视图发挥作用。由于该引擎为您提供了完整的用户界面实现,因此您无需从头开始开发单独的用户界面组件。
但是,如果采用传统的 MVC 模式,则需要特定于视图的代码在运行时监听模型数据的任何变化。
虽然这是一种有效的方法,但许多 Unity 开发人员选择使用 MVC 的变体,即控制器充当中介。在这里,视图并不直接观察模型。取而代之的是类似上图的操作。
MVC 的这种变体被称为模型视图演示器设计,或 MVP。MVP 仍保留了三个不同应用层的分隔功能。不过,每个部分的职责略有不同。
在 MVP 中,呈现器(在 MVC 中称为控制器)充当其他层的中间人。它从模型中获取数据,然后将其格式化,以便在视图中显示。MVP 切换哪一层处理输入。负责处理用户输入的是视图而不是控制器。
请注意事件和观察者模式在这一设计中的作用。用户可以与 Unity UI 的按钮、切换和滑块组件进行交互。视图层通过用户界面事件将输入发送回演示器,演示器则反过来操作模型。来自模型的状态变化事件会告诉演示者数据已经更新。演示者将修改后的数据传递给视图,视图会刷新用户界面。
Github 上有一个示例项目,展示了不同的编程设计模式,包括如何实现 MVP 变体的示例。
MVP 示例包括一个显示角色或物品健康状况的简单系统。该示例将所有内容都放在一个类中,将数据和用户界面混合在一起,但这在实际生产中并不能很好地扩展。添加更多的功能会变得更加复杂,因为你需要扩展它。此外,测试和重构也会造成大量开销。
相反,您可以采用更以 MVP 为中心的方式重写健康组件,首先将脚本分为Health和HealthPresenter。
在示例项目中,您可以点击射击圆盘来损坏目标对象(ClickDamage.cs),或使用按钮重置健康状况。这些事件会通知HealthPresenter(调用 "损坏"或 "重置"),而不是直接更改 "健康状况"。当 "健康"触发事件并通知HealthPresenter其值已更改时,UI 文本和 UI 滑块就会更新。
让我们深入探讨一下 "健康"组件是什么样的。在这个版本中,"健康"是 "模式"。它存储实际的健康值,并在该值发生变化时调用事件HealthChanged。Health不包含游戏逻辑,只有递增和递减数据的方法。
这样就能明确区分数据、数据展示方式和数据控制方式。
MVP(和 MVC)在大型和重用户界面的软件应用程序中大放异彩,但它并不局限于这些用例。如果您的游戏需要一个庞大的团队来开发,并且您希望在游戏推出后长期维护它,那么您可能会发现以下好处:
顺利分工: 由于将视图从演示程序中分离出来,用户界面的开发和更新几乎可以独立于代码库的其他部分。您的团队中有专业的前端开发人员吗?让他们来处理 View。
利用 MVP 和 MVC 简化单元测试: 这些设计模式将游戏逻辑与用户界面分开。因此,您可以模拟对象来处理代码,而无需在编辑器中实际进入 "播放 "模式。这可以节省大量时间。
可读、可维护的代码 使用这种设计模式,你会倾向于创建更小的类,从而使它们更容易阅读。较少的依赖关系通常意味着较少的软件故障点、较少的可能隐藏错误的地方以及更容易的测试。
虽然 MVC 和 MVP 在网络开发或企业软件中非常普遍,但往往要等到应用程序达到足够的规模和复杂程度,其优势才会显现出来。在您的 Unity 项目中实施这两种模式之前,您需要考虑以下几点:
你需要未雨绸缪: MVC 和 MVP 是更大的架构模式。要使用其中一种方法,您需要按责任划分班级,这需要一些组织工作,而且需要做更多的前期工作。设计模式的使用最好保持一致,因此你需要建立一个组织用户界面的惯例,并确保你的团队能够接受。
Unity 项目中并非所有内容都符合该模式: 在 "纯粹的 "MVC 或 MVP 实现中,渲染到屏幕上的任何内容都是视图的一部分。并非每个 Unity 组件(如网格渲染器)都能轻易分割数据、逻辑和界面。此外,简单的脚本可能不会从 MVC/MVP 中获得太多好处。
您需要判断您能从该模式中获益最多的地方。通常,你可以让单元测试来指导你。如果 MVC/MVP 可以促进测试,那么在应用程序的这一方面可以考虑使用它们。否则,就不要把图案强加在项目上。
您可以在免费电子书中找到更多关于如何在您的 Unity 应用程序中使用设计模式以及 SOLID 原则的技巧。 使用游戏编程模式提升代码水平.
如果您想更深入地了解如何使用 Unity UI 和 UI 工具包,请参阅详尽的指南、 Unity 中的用户界面设计与实现指南,该指南由用户界面专业人士编写。