| 前 言 用户体验是任何游戏的关键组成部分。用户体验不仅包括游戏剧情和游戏玩法,还包括图形运行的流畅程度,与多人服务器连接的可靠性,对用户输入的响应程度,以及最终应用文件的大小(因为现在普遍流行应用商店和云下载,超大的安装文件包可能让玩家望而却步)。便宜好用的AAA工业级游戏开发工具(例如Unity)的发布,大大降低了游戏开发行业的进入门槛。当然,玩家期望开发者提供的最终产品的功能和质量每天都在提高。不难想象,今后游戏的每一个方面都可以而且将会受到玩家和评论家的严格审查。 游戏性能优化的目标与用户体验息息相关。优化效果不佳的游戏可能会导致帧速率降低、死机、崩溃、输入滞后、加载时间长、运行时行为不稳定、物理引擎故障甚至电池功耗过高(在游戏进入移动设备时代之后,这一点尤其重要)。上述问题中的任何一项都有可能变成游戏开发人员最糟糕的噩梦,因为尽管总体来说我们已经做得足够好,但评论往往会集中在我们做得不好的一件事情上。 所谓“性能优化”就是充分利用可用资源,这些资源包括CPU资源(例如CPU周期和主内存空间)、图形处理单元(GPU)资源(例如显存VRAM和内存带宽)等。但是,性能优化还意味着确保没有单个资源在不适当的时间造成瓶颈,并且优先处理优先级最高的任务。即使是很小的、间歇性的卡顿,也很容易使玩家退出体验,打破沉浸感,并限制了我们创造预期体验的潜力。 决定何时退后一步并停止提高性能也很重要。在时间和资源无限的世界中,总会有另一种方法可以使游戏变得更好、更快或更易于维护。开发人员能够拥有无限的时间和资源吗?不能。所以我们要懂得在一定的程度适可而止,在开发过程中既要确保产品达到可接受的质量水平,又不能无限度地追求进一步的改变和提升,事实上,有些改变几乎不会带来任何明显的好处。 决定某项性能问题是否值得解决的最佳方法是回答一个提问“用户会注意到吗?”,如果对这个问题的回答为“否”,那么性能优化将是一种浪费。在软件开发行业有一句 老话: “过早的优化是万恶之源。” 过早优化的主要罪过是重新编写和重构了代码,目的是要提高性能,但是却没有任何必要性的证明。这可能意味着要么是在尚未显示出性能问题甚至问题根本不存在的情况下(如前文所述,如果某项问题用户根本注意不到,则可以认为该问题不存在)进行了更改,要么仅仅是因为我们主观上认为性能问题可能源于某个特定领域就进行了更改,但是在此之前却并没有证据证明它是真的。犯下这样的错误是令人沮丧的,因为它使软件开发人员付出了巨大的努力,但是却毫无收获。 本书旨在为我们提供检测、修复应用程序中的性能问题所需的工具、知识和技能,无论这些问题源自何处。实际上,它们可能源于诸如物理、渲染等软件子系统中的硬件组件(如CPU、GPU或RAM),也可能源于Unity引擎本身的硬件组件。 此外,我们节省的资源越多,在使用相同硬件系统的Unity引擎中可以做的事情就越多,从而使我们能够制作出更多有趣且富于变化的游戏。 总之,如果能有效掌握性能优化技巧,那么这将为我们的作品提供在充斥着大量新游戏的市场中脱颖而出的机会。 本书涵盖的内容 第1章“检测性能问题”,介绍了Unity Profiler和一系列性能分析方法,以分析我们的应用程序,检测性能瓶颈并执行根本原因分析。 第2章“脚本编写策略”,介绍了有关Unity C# 脚本代码的最佳实践,如何最大程度地减少组件开销,改善对象间的通信等。 第3章“批处理的好处”,探讨了Unity的动态和静态批处理系统,通过它们可以减轻渲染系统的负担。 第4章“快速启动艺术资产”,可帮助开发人员了解艺术资产背后的基础技术,并掌握如何避免导入、压缩和编码等方面的常见陷阱。 第5章“更快的物理引擎”,详细讨论了Unity物理系统或物理引擎在3D和2D游戏中的细微差别,以及如何正确组织物理对象以提高性能。 第6章“动态图形”,深入介绍了渲染系统的性能分析,讨论了如何改进在GPU或CPU中出现渲染瓶颈的应用程序,以及如何针对移动设备进行性能优化。 第7章“精通内存管理”,介绍了Unity引擎、Mono Framework的内部工作原理,以及如何在这些组件中管理内存,以保护我们的应用程序免受堆分配和运行时垃圾回收的 影响。 第8章“提示和技巧”,详细介绍了专业开发人员用来改善项目工作流程和场景管理的多种有用技术。 充分利用本书 本书的大部分内容将重点介绍Unity 5.x版本中的功能。大多数技术都可以应用于Unity 4.x项目,但可能需要升级到Unity 4 Pro Edition才能访问其中的某些技术(例如遮挡剔除、静态批处理,甚至是Profiler本身)。 本书适合的读者 本书面向具有Unity大部分功能经验的中级和高级Unity开发人员,以及希望最大程度地提高游戏性能或解决特定瓶颈的人员。游戏性能瓶颈多半是由于CPU过载、运行时峰值、内存访问速度慢、内存碎片、垃圾回收、GPU填充速率差或内存带宽等引起的,本书将教给开发人员确定瓶颈问题根源所需的技术,并帮助开发人员探索多种方法以减少它们对游戏性能的影响。 涉及脚本和内存使用的部分将需要读者熟悉C#语言,而涉及着色器优化的领域则需要读者对计算机图形学有基本的了解。 本书约定 本书将可以看到许多区分不同类型信息的文本样式。以下是这些样式的一些示例以及对它们的含义的解释。 (1)界面词汇以粗体表示,后面使用括号附加对应的中文含义,方便读者对照查看。以下段落就是一个示例: 请确保在构建应用程序时启用了Use Development Mode(使用开发模式)和Autoconnect Profiler(自动连接性能分析器)标志。 (2)代码块显示如下: public class TestComponent : MonoBehaviour { void Update() { if (Input.GetKeyDown(KeyCode.Space)) { PerformProfilingTest(); } } } (3)当我们希望引起你对代码块特定部分的注意时,相关的行或项目将以粗体显示: public class TestComponent : MonoBehaviour { void Update() { if (Input.GetKeyDown(KeyCode.Space)) { PerformProfilingTest(); } } } (4)新术语和重要单词以粗体显示,并提供了中英文对照的形式: 为了创建可以保存Profiler数据的工具,不妨使用协程(Coroutine)。通常来说,一种典型的方法将一口气从头到尾执行,但是,协程是非常有用的构造,它允许开发人员编写可以暂停执行的方法,直到以后或事件发生时继续执行,这被称为挂起(yielding),因为它是通过yield语句完成的。 图标旁边的文字表示警告或重要的信息。 图标旁边的文字表示提示或技巧。 下载示例代码文件 读者可以从www.packt.com下载本书的示例代码文件。 |