
Unity 项目的测试和质量保证技巧
本文介绍了不同的测试实践,可帮助您使用 Unity 发布更稳定的项目。
测试或质量保证(QA)是贯穿整个游戏开发周期的关键流程。有经验的开发者都知道,你写的任何代码都需要经过测试。
不管您是独立개발자者还是大型团队的成员(成熟的工作室通常有专门的QA工程师),都可以采用一系列测试和QA方法。
如果你喜欢玩和/或观看体育比赛,那你知道在许多比赛中,只有防守才能赢得冠军。你可以将 QA 过程视为一种防御策略,在发布具有最佳性能和稳定性的游戏时不留任何机会。
为什么测试和质量保证很重要?
测试对于发现代码中的错误、美术作品中的视觉瑕疵或游戏设计和玩法中的用户体验问题等问题至关重要。你可以开发出技术印象最深刻的游戏,但如果它十之八九会崩溃,那么你的用户很快就会放弃它。
何时应在游戏开发周期中实施测试?
避免将测试工作拖到游戏开发过程的末尾。与其将测试视为序列中的一个阶段,不如将其视为一个持续的过程,为游戏开发的其他阶段提供支持。在整个制作过程中和发布之前测试您的想法和原型。每次为游戏发布的更新都重复这一过程。
有一系列不同的测试技术可能更适合项目的不同阶段。
谁负责测试和 QA?
您是小型工作室的成员,但没有专门的 QA 团队?找朋友工作组帮忙进行测试,或选择第三方QA提供商帮忙。即使是有内部 QA 团队的工作室也会经常使用外部公司提供额外的测试服务,例如本地化测试 (LQA)。
玩家测试可以看作是 QA 的一个子集,它有助于确保您的游戏与目标受众和市场产生共鸣。这个流程可以让玩家在开发阶段提供宝贵的反馈来改进游戏。
参与玩家测试的人员因测试的具体目标而异。但是,一般来说,让代表游戏目标受众的多样化玩家群体参与进来非常重要。通过让不同类型的玩家参与玩家测试,游戏开发者可以从多个角度收集反馈,确保游戏能够吸引更广泛的受众。
如何对游戏进行问答和测试?
你可以在以下章节中了解常见的测试技术。这些方法可以组合使用,以确保代码库的性能尽可能流畅。
在目标平台的一系列设备上测试游戏也很重要。这尤其适用于移动游戏;您需要在不同的操作系统、屏幕大小和最低规格移动设备上进行测试。这样做有助于确定最低设备要求,并且当您向应用程序添加更多功能时,应经常重新审视每个类别。
在各种平台上进行测试不仅是为了发现潜在的游戏中断问题,还希望了解长期或间接的影响,例如手机游戏的电池耗尽或过热。

单元测试
单元测试是指单独测试游戏的各个单元或组件,帮助确保在开发过程的早期发现错误,并确保代码更改不会破坏现有功能。
单元测试是通过编写行使代码特定行为的小测试用例来完成的。测试可以在单个脚本、游戏对象或游戏的特定功能上运行。
在游戏开发中应使用手动和自动化单元测试方法。
手动单元测试
玩家需要手动测试游戏的特性和功能。运行手动测试非常重要,因为自动化测试可能无法发现一些问题,例如 UI 错误或不平衡或执行不力的游戏玩法或设计。
Unity中人工单元测试的一个实例是,为一项功能添加一个测试条件,并使用Debug.Log在Unity的播放模式下输出通过或失败的标准(测试情景的输出)。
自动化单元测试
自动化单元测试需要编写代码来自动单独测试单个单元或代码片段。在 Unity 中,您可以编写脚本、组件和可以作为测试套件一部分运行的其他游戏代码单元的测试。
Unity Test Framework(UTF)软件包为开发者在Unity Editor中以Edit和Play模式编写自己的自动化测试提供了一个框架。UTF 在任何引用 NUnit 的程序集内部查找测试。此类程序集称为TestAssemblies。运行模式和编辑模式测试需要放在单独的程序集内进行。
UTF 在编辑器中提供了一个 Test Runner 窗口,帮助您运行和管理测试用例。
由于UTF使用的是TestAssembly Definition(测试程序集定义),你需要将项目拆分成运行时程序集定义。在开发过程的早期进行规划时,这更容易实现;它还鼓励您编写模块化代码。
Unity软件包,即Performance Testing Extension是可与UTF一起使用的扩展。它提供额外的 API 进行测量,并提供来自测试用例的自定义指标。
通过阅读Unity Test Framework for video game操作指引,了解如何开始使用Unity Test Framework。

测试驱动开发
测试驱动开发(Test-driven development,TDD)是指在实际编写代码之前编写功能测试。该过程通常涉及编写失败的测试,编写使测试通过所需的最小代码量,然后重构代码以使其更易于维护,然后继续设计下一个测试用例。
在游戏开发中,TD 是很少见的(在主流软件开发中更常见)。这可能是因为原型设计和制作有趣又吸引人的游戏过程有悖常理。
但是,它可以加快识别游戏中断部分的过程,因为任何中断游戏的更改都会立即导致失败的测试案例。
有关Unity中TDD的详情,请参阅博客文章 " 使用Unity Test Runner测试Test-Driven Development。 "
代码覆盖率
如果你想进行TDD或单元测试, 可以考虑使用Unity Code Coverage包。当与 UTF 一起使用时,Code Coverage 包可以显示项目中哪些代码行正在进行测试,以帮助您确定项目中易受攻击或未测试的部分。
Code Coverage也可以在运行模式下测试游戏时生成报告。这将为您显示定期运行测试的代码部分,即使它们不在单元测试的范围之内。然而,虽然 Code Coverage 报告可以显示测试中涵盖了哪些代码行,但它不会显示逻辑在代码中经过的不同路径。
见博客文章 " Code Coverage:找出测试中的差距”以了解更多信息。
集成测试
集成测试是一种同时测试系统不同组件以确保它们正常工作的技术。这可能包括测试不同的游戏对象、脚本或系统在游戏中如何交互。由于范围较广,集成测试可以帮助发现单元测试中可能未显示的错误,例如数据流或组件之间通信的问题。
比如,我们可以为整个序列编写一个整合测试,而不是使用单个单元测试:玩家发射武器来实例化子弹,子弹击中敌人并杀死他们,玩家杀死敌人可获得分数,当玩家达到一定分数时解锁成就。
您可以使用 UTF 在 Unity 中构建集成测试。使用 SetUp 和 TearDown 方法,您可以创建环境以同时测试多个系统。可以模拟玩家逻辑和输入,特别是如果您已经使用命令模式实现它们(如果您正在使用新的输入系统,则很可能已经使用 ) , 以便测试玩家输入到游戏逻辑的完整流程。
回归测试
回归测试是一种检验软件或功能在被修改或更新后能否正常工作的方法。回归测试的目的是确保代码库的更改不会在软件中引入新的错误或回归。该技术最适合经常更新的大型复杂应用程序,例如实时游戏,在这些应用程序中,可能有许多不同的组件以意想不到的方式交互。
随着游戏世界和机制的扩展,对回归测试的需求也在不断增加,而这又会增加成本。因此,必须尽可能将其自动化。回归测试应该与新功能的开发同时进行,特别是当您面向多个平台时。
虽然回归测试最适合大型和实时游戏,但其他因素(例如软件复杂性、更改或更新频率以及受影响功能(任务或安全关键系统)的关键重要性)也决定了其需求。
功能测试
功能测试通过对照系统或软件应用程序的功能要求对其进行测试来评估其功能。它涉及测试系统的特性、用户界面、数据库交互以及影响其行为和功能的其他方面。功能测试的目的是验证系统或应用程序是否满足客户或最终用户的要求和规范。
大多数单元测试专注于代码的特定路径,测试它是否根据某些输入返回正确的输出。它无法测试游戏是否达到了预期效果。
功能测试就是这种方法。将每个功能或特性与原始设计进行比较,看看输出是否满足预期。这可能包括测试游戏的控件、游戏机制和整体用户体验。
在开发游戏时,牢记功能测试,用“当这个,然后那个”的方法来创建任务可能会很有用。例如,当玩家按下空格键时,角色应该跳跃:这既是对개발자者有关他们应如何实现功能的说明,也是测试人员进行测试的验收标准。有时,功能可能包括一些相关的验收标准,例如功能何时可以使用和何时不能使用。但他们一般应该专注于单一功能。
当需求被明确定义和界定时,功能测试是最强大的。因此,与自由职业者或工作室签约来提供游戏玩法或游戏世界素材资源组件非常有用。
您可以运行自动化和手动功能测试。应同时运行“黑盒”测试(在不了解其内部工作原理的情况下测试系统)和“白盒”测试(在了解其内部工作原理的情况下测试系统)。

性能测试
性能测试包括测试游戏,以确保其在不同硬件和软件配置上流畅而高效地运行。这与性能分析和一般的性能优化工作流程密切相关,这种做法可以帮助确定可能影响游戏性能的性能瓶颈或问题。
关键目标是评估系统或应用程序在不同工作负载条件下的性能。在游戏开发中,性能测试用于衡量游戏是否以可接受的性能、权重、响应能力和稳定性水平运行,以及是否以最有效的方式使用内存。
不同类型的性能测试包括:
- 负载测试:确定游戏在承受繁重工作负载时的表现
- 压力测试:评估游戏如何处理意外情况,例如玩家活动的突然增加
- 耐久测试:评估游戏的长期表现
Unity Profiler
Unity的Profiler工具能帮助你在开发游戏时分析游戏的表现。它可以在编辑器中(在开发时提供概览)或通过电缆或通过本地网络连接到机器的任何设备上,提供对游戏在目标设备上运行的准确分析。
可以扩展Profiler,以自定义要捕获的数据类型的显示方式及其在Profiler窗口中的可视化显示方式。
在Unite 2022会话级别/会话次数 " 如何自定义Unity Profiler中的性能指标 " 中详细了解如何自定义Profiler。
您还可以编写自己的工具来创建自动化性能测试。若你想了解这个方法,请观看Unity Valley开发者ustwo Games在Unite 2022上的演讲:“制作《Alba》:如何构建高性能的开放世界游戏。”

A/B 测试
测试并不局限于发现错误和监测性能。有时,您可能需要比较游戏功能的两个版本,以确定哪个版本能获得更多玩家的用户渗透度并有更好的表现。这称为A/B测试。
A/B 测试对于修改会影响游戏平衡性但游戏机制不变的角色或武器的统计数据非常有用。其他例子还包括用于比较不同教程、游戏机制或用户界面有效性的测试。通过分析从两组收集的数据,您可以确定哪个游戏版本或功能更有效,并根据数据做出将哪些更改纳入最终产品的决策。
A/B测试是指将玩家随机分成两组:一组玩家玩游戏或功能的原始版本(对照组),而另一组玩家玩游戏或功能的修改版本(实验组)。
关键在于收集一小部分玩家受不同变化影响的数据,以帮助你做出设计决策,将哪些方法作为广泛更新发布。
A/B 测试有助于改善用户体验,提高玩家用户渗透和用户留存。对于拥有庞大用户群的游戏来说,即使用户渗透或用户留存方面的微小改进也可以产生显著影响,这一点尤其有用。
A/B 测试通常作为后端服务提供,玩家甚至不知道他们正在使用不同的版本。Unity Gaming Services (UGS)有工具可帮助你在游戏中运行A/B测试,你可以在这里了解更多详情。你也可以查看UGS Use Cases, 这是我们后端服务的样本集合, 探索如何在游戏中进行A/B测试的样本。
诊断和测试工具
Cloud Diagnostics Advanced是一种由Backtrace驱动的崩溃报表和分析工具,与Unity集成,为开发者提供有关游戏中崩溃和异常的详细信息。崩溃发生时,Cloud Diagnostics Advanced 会捕获崩溃时游戏状态的快照,包括有关环境、调用堆栈、堆和寄存器的信息。然后将该快照发送到 Backtrace 服务器,对其进行分析以确定崩溃的根本原因。
Cloud Diagnostics Advanced 还提供了详细的 Analytics 和报表工具,可帮助您确定游戏性能和稳定性的长期趋势和模式。重复数据消除算法根据代码中的根本原因对常见的崩溃进行聚类,以帮助确定优先修复的错误,从而提高对大多数玩家的稳定性。
为游戏开发者提供更多质量保证资源
无论使用哪种测试技术,都必须制定游戏测试计划,并确保测试成为开发过程中不可或缺的一部分。通过结合使用这些技术,可以确保您的 Unity 游戏达到最高质量并可用于生产环境。
程序员的新电子书系列现已在Unity免费开放。每本指南都由经验丰富的程序员编写,针对对开发团队重要的特定主题提供了最佳实践。
创建C#风格指南:编写更简洁、可扩展的代码来指导团队制定风格指南,帮助统一方法,从而创建更一致的代码库。
用游戏编程模式提高代码水平着重介绍使用SOLID原则和通用编程模式在Unity项目中创建可扩展游戏代码架构的最佳做法。
在Unity中使用ScriptableObjects创建模块化游戏架构提供了在游戏制作中部署ScriptableObject的最佳做法。
我们制作这个系列是为了向最有经验的创作者提供可操作的技巧和灵感。但它们不是规则书!构建 Unity 项目的方法有很多;在部署之前与同事评估每个建议、技巧和模式的优劣。
在Unity最佳实践中心查找更多高级指南和文章。