用游戏编程模式提升你的代码水平


如果你写过面向对象的编程语言,那你可能听说过SOLID原则、MVP、单例、工厂和观察者模式。我们最新的电子书将介绍如何在你自己的Unity项目中应用这些原则和模式,搭建可扩展的游戏代码架构。
你遇到的每一个软件设计问题都可能已经被上千名其他开发者遇到过。尽管直接向他们请教不太现实,但你依然可以学习他们的设计模式和决策。
通过在项目中实施常见的游戏编程设计模式,你可以有效地建立和维护一个干净、有序和可读的代码库,为游戏、开发团队和业务的扩展打下坚实的基础。
我们经常听到有社区用户在说,将SOLID和KISS等设计模式和原则结合到日常开发中并非易如反掌。这就是为什么我们的免费电子书、 用游戏编程模式提升代码水平解释了众所周知的设计模式,并分享了在您的 Unity 项目中使用这些模式的实用示例。
这本电子书由Unity内外的专家撰写,可以扩大你的开发工具箱,让项目更快取得成功。请在下文继续了解指南的内容。
设计模式是解决常见软件工程问题的方案。它们并非可以复制粘贴到代码中的现成代码,但可以帮助你建立更大的可扩展应用。
只要坚持在项目中应用这些设计模式,你就可以提高代码的可读性,使代码库更加简洁。设计模式不仅可以减少重构和测试的时间,还可以加快新人上手和开发过程。
当然,每一种设计模式都有着优缺点,它可能是额外架构维护工作,或是在开始时要做更多准备。因此你必需衡量“成本-收益”,确定收益是否值得投入额外的工作。每个项目的情况都有不同,请因项目而制宜。
KISS代表“keep it simple, stupid(保持简单、无脑)。”这一原则的主旨是避免不必要的复杂性,因为简单的系统有助于用户接受和互动。
注意,“简单”并不等同于“轻松”。让某物变得简单是指让它更集中。同样的功能虽然也能不采用KISS模式开发(这样甚至更快),但快速轻松地造出来的东西不一定简单。
如果你不确定某个模式是否适用于特定问题,可以先等等看,直到模式能自然而然地应用进来。不要在学到一个新模式后就急着大显身手。只在需要时使用它。
这种理念也是本电子书的编写初衷。你可以在指南里为构思代码的新组织方法而寻找灵感,但不必严格遵守书中的规则。
现在,我们来谈谈一些关键的软件设计原则。

SOLID是软件设计五个核心基本要素的首字母缩写。你可以把它们看作编程时需谨记的五条基本规则,它保证了面向对象设计的灵活性和可维护性。
SOLID 原则由罗伯特-C-马丁(Robert C. Martin)在论文《设计原则和设计模式》中首次提出。这些首次发布于2000年的原则在今天仍然适用于编程及Unity的C#编程:
- 单一责任是指每个模块、类或函数只负责一件事,并只封装这部分逻辑。
- 开放-封闭(Open-closed)是指类必须对扩展开放,但对修改封闭;这意味着要在不修改原始代码的情况下构建类,以创建新的行为。
- 利斯科夫替代法规定,在使用继承时,派生类必须可替代基类。
- 接口隔离规定,任何客户端都不应被迫依赖其不使用的方法。客户端应只应用必须的方法。
- 依赖反转规定,高层模块不应直接从低层模块导入任何内容。两者都应依靠抽象层交互。
在这本电子书中,我们用插图展示了每条原则,并清晰解释了这些原则在Unity中的应用。有时,坚持SOLID原则可能会产生额外的前期工作。部分功能将需要被重构为抽象概念或接口,但长期坚持下来总会有回报。
近二十年来,这些原则一直主导着企业级的软件设计,因为它们非常适合于扩展大型应用。如果你不确定如何使用它们,请再次参考KISS原则。保持简单,不要为了做而做。在时机恰当时它们自然会发挥作用。
如果您有兴趣了解更多信息,请查看 Productive Edge 公司的 Dan Sagmiller在 2017 年奥斯汀团结大会上发表的 SOLID 演讲。
设计原则和设计模式有什么区别?你可以将SOLID原则视为编写面向对象代码的框架或基础方法。而设计模式虽然是避免日常软件问题的解决方案或工具,但它们并非即食食品,或能实现特定结果的具体算法。
设计模式可以被看作一张蓝图。它只提供总体规划,具体的施工还得靠你自己。比如两个程序可以遵循相同的模式,但代码非常不同。
当开发者在工作中遇到相同的问题时,许多人肯定会想出类似的解决方案。一旦某个解决方案被足够多的人使用,那它可能会发展成一种模式,并获得一个名字。
当今的许多软件设计模式都源于开创性著作《Design Patterns》:Erich Gamma、Richard Helm、Ralph Johnson 和 John Vlissides 合著的 Elements of Reusable Object-Oriented Software 。本书介绍了在各种日常应用中发现的23种类似模式。
原作者通常被称为 "四人帮"(GoF),你也会听到有人把原始模式称为 GoF 模式。虽然本书引用的例子大多是C++(和Smalltalk),但你仍然能将他们的想法应用于任何面向对象的语言,如C#。
自 "四人帮 "于 1994 年首次出版《设计模式》 以来,开发人员已在包括游戏开发在内的多个领域建立了数十种面向对象的模式。


虽然不学习这些设计模式也能从事游戏编程的工作,但掌握它们能帮你成为一个更好的开发者。毕竟设计模式之所以叫设计模式,正是因为它们经常被用于解决常见的问题。
软件工程师们一直能在正常的开发过程中找到它们。甚至你自己都可能在不知不觉中应用过一两种。
训练自己寻找它们。这样做可以帮助你:
- 学习面向对象编程:设计模式并不是埋藏在 StackOverflow 神秘帖子中的秘密。它们是克服日常开发难题的常见方法。有模式就意味着有其他开发者处理过同样的问题。即便你不关注模式,其他人也在使用它们。
- 与其他开发人员交流:在团队沟通时,模式可以作为一种速记方法。一提到“命令模式”或“对象池”,有经验的Unity开发者立即就能知道你要实现的是什么。
- 探索新框架:当你从资产商店导入一个内置软件包或其他东西时,难免会偶然发现这里讨论的一个或多个模式。认识设计模式能帮你了解一个框架的工作方式及背后的构思。
如之前所述,并非所有设计模式都适用于游戏。不要用马斯洛的锤子去找它们,否则,你可能只会找到钉子。
与任何其他工具一样,设计模式的实用性取决于语境。每一种模式在特定情况下确实有好处,但也有其弊端。软件开发过程中的每一个决定都会带来妥协。
你是否在运行期间生成了大量的GameObject?它们是否会影响性能?重构代码可以解决这个问题吗?留意这些设计模式,在时机成熟时再搬出它们来解决手头的问题。
除了 "四人帮 "的《设计模式》,罗伯特-尼斯特罗姆(Robert Nystrom)的《游戏编程模式》(Game Programming Patterns)也是另一个杰出的资源,目前可免费获得网络版。作者以一种毫不废话的方式详细介绍了各种软件模式。
你可以在我们的新电子书里深入了解这些常见设计模式,如工厂(factory)、对象池、单例、命令、状态和观察者模式,以及Model View Presenter (MVP)等等。书的每一节都解释了模式及其优缺点,并包含一个Unity的应用实例,方便你在项目中更好地使用。
Unity本身已经实施了几种既定的游戏开发模式,你不必自行编写。它们有:
- 游戏循环:所有游戏的核心都是一个无限循环,它的运行必须不受时钟速度的影响,因为为游戏应用程序提供动力的硬件可能差别很大。为了应付运行速度各异的计算机,开发者通常需要使用一种固定的时间步(预设好了每秒帧数)和一个变化的时间步,后者用于测量上一帧到这一帧的耗时。
Unity 会处理这个问题,因此您不必自己实现。你只需要用MonoBehaviour的Update、LateUpdate和FixedUpdate等方法来开发游戏玩法就行了。 - 更新:在游戏程序中,您经常会一帧一帧地更新每个对象的行为。你的确可以在Unity里重新编写更新代码,但MonoBehaviour类会自动执行同样的操作。正确地使用Update、LateUpdate或FixedUpdate方法能让你在“游戏时钟”的每一跳修改GameObjects和组件。
- 原型:您经常需要在不影响原始对象的情况下复制对象。这种创造模式解决了复制相似物体的问题。而你不必为生成游戏里的每一种对象而定义一个单独的类。
Unity 的预制系统为 GameObjects 实现了一种原型设计形式。你可以完整复制一个模板对象及其组件。覆盖特定属性以创建Prefab 变体,或将Prefab 嵌套在其他Prefab内以创建层次结构。使用特殊的Prefab 编辑模式,可单独或在上下文中编辑 Prefab。 - 组件:大多数从事 Unity 工作的人都知道这种模式。与其将许多行为塞进一个大类里,不如建立只负责一件事的小组件。
如果使用组合来挑选组件,就可以将它们组合起来,实现复杂的行为。添加Rigidbody和Collider组件用于物理效果,或添加MeshFilter和MeshRenderer来绘制3D几何。每个GameObject在拥有一系列的组件后才显得丰富和独特。
