搜索 Unity

Two monitors and a laptop
Two monitors and a laptop
分享

Is this article helpful for you?

Thank you for your feedback!

我们最近发表了两篇博文:加快编辑器工作流的五种方法加快艺术工作流,这两篇博文都是基于我们为专业开发者编写的电子书:使用Unity 2020 LTS提高生产力的70+技巧。本文属系列第三篇也是最后一篇,我们将重点介绍能让编程事半功倍的工作流程和功能。先来看看怎样减少测试时的编译时间。

利用Enter Play Mode设置节省编译时间

项目在进入Play模式时会与正常运行版一样的方式运行。在退出Play模式时,编辑器内的所有改动都会被重置。

在进入Play模式之际,Unity会执行两段重要的操作:

  • Domain Reload(重新加载域): Unity将完成当前脚本的备份、卸载和重现。
  • Scene Reload(重新加载场景): Unity摧毁并重新加载场景。

随着脚本和场景变得越来越复杂,这两个流程所花的时间也会越来越多。

这时,如果脚本不再有任何改动,你可以在Enter Play Mode Settings(Edit > Project Settings > Editor)来缩短编译时间。Unity可以禁用Domain Reload、Scene Reload或同时禁用两者,让Play Mode的进入和退出速度更快。

如果你打算继续修改脚本,别忘了重新启用Domain Reload就行了。同样地,如果场景层级视图有了改动,你也应该重新启用Scene Reload,否则引擎可能会出现意想不到的行为。

The effects of disabling the Reload Domain and Reload Scene settings

通过设定程序集来控制编译

一个程序集是一种C#代码的集合,是多个类型(Type)和资源相互关联形成的功能逻辑单元。默认情况下,Unity会将几乎所有的游戏脚本编译到预设的Assembly-CSharp.dll程序集中。这种方法非常适合小型项目,但它有一些缺点:

  • 每当有脚本被改动,Unity需要重新编译所有其他脚本。
  • 某个脚本可以访问任意其他脚本中定义的类型。
  • 应用每次部署都需编译一遍全部的脚本。

我们可以通过自定义程序集,来提高其模块化程度和重复使用性。自定义的程序集可将部分脚本排除在默认程序集外,还能控制脚本的访问权限。

你可以像上图一样把脚本分成多个程序集。这里,Main程序集中的任意改动都不会影响到Stuff中的代码。同样的,不依赖其它程序集的Library可以很简单地在其他项目中再度使用。

.NET的程序集自带了各类C#程序集的一般定义。请参考Unity文档的Assembly Definitions部分来详细了解如何在Unity中编写自己的程序集。

使用脚本模板定制新脚本

你是否遇到过在新建脚本后需要编写多段重复代码的情况?是否会机械地加上命名空间或删除Update函数?如果有,那就来试试脚本模板功能吧。用模板来减少几次键盘的敲打,统一整个团队的编程风格。

实际上,在你每次创建新脚本或着色器时,Unity本身就会使用模板。模板保存于

%EDITOR_PATH%\Data\Resources\ScriptTemplates

  • Windows:C:Program Files\Unity\Editor\Data\Resources\ScriptTemplates
  • Mac:/Applications/Hub/Editor/[版本号]/Unity/Unity.app/Contents/Resources/ScriptTemplates

而这个是引擎默认的MonoBehaviour模板:

81-C# Script-NewBehaviourScript.cs.txt

除此之外,还有着色器、其它脚本和程序集定义的模板。

若想为特定项目创建的脚本模板,你可以新建一个Assets/ScriptTemplates文件夹,将模板复制到文件夹下来覆盖默认模板。

你也可以直接修改所有项目的默认脚本模板,但在修改之前请备份好原文件。

默认的81-C# Script-NewBehaviourScript.cs.txt文件看起来是这样的:

请注意这两个关键词:

  • #SCRIPTNAME#代表了创建时输入的文件名或默认文件名(如NewBehaviourScript)。
  • #NOTRIM#代表了大括号内的空行。

在修改后,你需要重新启动Unity编辑器,接着所有新建的MonoBehaviour脚本便都会应用新模板了。

你也可以以类似的方式修改其他模板。注意在项目文件夹以外的地方分别保留一份原模板和新模板,以便不时之需。

使用特性定制检视器等编辑器元素

Unity带有的多种特性,可加在类、属性或函数的开头,来让其显现特殊行为。C#的特性需加在一个方括号内。 

下方为几种脚本中常见的特性:

除了上方例子外,Unity的C#特性还有许多。你可以在保留值的前提下 为变量更名,或者在没有空游戏对象的情况下调用逻辑。请在文档的Scripting API部分查看所有特性及其功能。

你甚至可以创建并应用自己的PropertyAttribute

定制编辑器窗口和检视器

Unity最强大的功能之一是其可扩展的编辑器。使用UI ToolkitIMGUI模式可用于制作编辑器UI、自定义编辑器窗口和检视器。

UI Toolkit的制作流程类似于标准网页开发,它使用的UXML markup语言模仿了HTML和XML,可用于编写UI和可重复使用的UI模板。你还可以用Unity Style Sheets (USS)来修改UI的视觉风格和行为。

你也可以使用即时模式的UI,即上文提到的IMGUI。首先在脚本中继承Editor基本类,然后在函数前加上CustomEditor特性。

这些都是自定义检视器的方法。

下方的自定义编辑器改变了MyPlayer脚本检视器界面:

请在Creating User Interfaces (UI)中详细了解怎样使用UI Toolkit或IMGUI自定义编辑器。请观看Gettings Started with Editor Scripting教程中快速了解UI Toolkit。

使用Addressables(可寻址)系统简化资源管理

Addressable Asset System可简化游戏资源的管理方式。你可以将场景、预制件、文本等任意资源标记为“Addressable”,并加上一个独特的名称,然后用这个名称在任意位置调用资源。

在游戏和资源间建立一层抽象层可以让DLC打包等资源处理相关的流程更为简单,也能方便系统引用本地或网络上的资源。

在本例中,Addressables会跟踪所有的预制件。

要想使用系统,你须先在Package Manager中安装Addressables软件包,为项目做好基本设置。安装完成后,项目的每一个资源或预制件都应该有一个“Addressable”选项。勾选检视器资源名称下的选项便可为其分配一个唯一的默认地址。

启用Addressable后生成的默认Addressable Name

在设置完成后,资源将出现在Window > Asset Management > Addressables > Groups窗口中。

你可以在Addressables Groups中查看每个资源的地址及路径。

系统还带有另一个便利功能:你可以分开为每个资源修改Address字段的地址,也能一次性修改全部的地址。

你可以在菜单中单次修改Addressable Name,或单独进行修改。

默认构建脚本可生成Addressable Group资源集。

将资源捆绑成集合,便将资源集托管至远程服务器,或在本地进行分享。不论资源存储在哪个路径,系统都可以使用Addressable Name字符串检索文件。

Addressable资源现在支持使用Addressable API进行调用。

对比之下,如果没有Addressable,你需要遵循以下步骤来实例化预制件:

这样做的缺点在于所有预制件(如prefabToCreate),不论有没有必要,都会被加载到内存中。

如果使用Addressables,则:

这里,系统会使用地址字符串来加载资源,意味着预制件只会在需要的时候被加载到内存中(我们在CreatedPrefabWithAddress方法下调用了Addressable.Instantiate)。此外,你也可以使用Addressable来控制上层资源(如某预制件的父对象)的引用,在资源没用后自动在内存中卸载集合及下属资源。

Tales from the optimization trenches: Saving memory with Addressables一文中包含了怎样使用Addressable Group优化内存的例子,而Addressables: Introduction to concepts教程则能让你快速了解如何在项目中使用Addressable Asset System。

在线游戏运营:使用Addressable实现云端内容分发

如果你正在运营一款在线游戏,你可以将Addressables与Unity的Cloud Content Delivery(云端资源分发,CCD)组合使用。由Addressable系统存储和分类的游戏资源可由系统自动检索、调用,这些资源接着可借助CCD直接推送到客户端,无需修改任何游戏代码。游戏程序可以有更小的体积,玩家们也不必在每次重大更新时重新下载、安装新的客户端。请在这篇博文中详细了解Addressable与CCD的整合方法。

使用前处理器指令控制编译行为

Platform Dependent Compilation(平台独立编译)功能允许你针对特定的平台划分出需编译、执行的代码。

例:使用#if编译指令运行具体平台的#define指令

DEVELOPMENT_BUILD #define可用于识别脚本是否运行在设置了特定Development Build的运行版中。

你可以根据特定的Unity版本和/或编程后端来有选择地进行编译,甚至能在编辑器中编写自定义的#define指令。打开Player Settings下的Other Seetings,找到Scripting Define Symbols来创建自定义指令。

请在手册的Platform Dependent Compilation一节详细了解Unity的前处理器指令。

善用ScriptableObject(可编程对象)

ScriptableObject是一种可在脚本外储存大量数据的数据容器。此类对象会尽量降低数据重复性,减少项目的内存占用。请在我们的电子书或在说明文档中详细了解ScriptableObject的使用。

请观看Better Data with ScriptableObjects in Unity教程来快速学习可编程对象的妙用,或观看Achieve Better Scene Workflow with ScriptableObjects来了解怎样用可编程对象实现场景管理。

优化技巧

我们推荐使用MessagePackProtocol Buffers等二进制格式来保存数据,不要使用JSON、XML等文本类数据格式。二进制格式相较于后者可节省内存占用、性能问题更少。

选择最适合你的IDE

Unity支持以下几种集成开发环境(IDE):

  • Visual Studio:Windows与macOS最常用的IDE
  • Visual Studio Code:Windows、macOS、Linux
  • JetBrains Rider:Windows、macOS、Linux

所有三种IDE的整合文件都打包在了一个软件包中,包可在Package Manager中下载。

IDE整合文件包

Visual Studio默认会与Unity一起安装。如果你想使用另一种IDE,可在Unity > Preferences > External Tools > External Script Editor下选取自己的代码编辑器。

基于ReSharper打造的Rider在兼具前身的大部分功能外,还支持Unity(C# 8.0).NET 4.6脚本运行时的C#调试。更多详情请参阅JetBrains文档的Rider for Unity部分。

VS Code是一款免费的代码编辑器,支持脚本调试、单任务运行和版本控制。若想在Unity中使用VS Code,请先安装Mono(macOS、Linux)、Visual Studio Code C#Visual Studio Code Debugger for Unity(尚无官方支持)。

每种IDE都有自己的优点,请在集成开发环境(IDE)支持一节详细了解哪个IDE最适合你。

请在我们的电子书中学习几种有益于开发的快捷键,观看Visual Studio Tips and Tricks to Boost Your Productivity来学习怎样优化自己的编程流程。

若想继续探索JetBrains Rider,请观看Fast C# scripting in Unity with JetBrains Rider,或在这里学习几种Rider编辑器的使用技巧

运行模式调试

Unity Debugger支持在运行模式下调试场景中的C#代码。你可以在代码编辑器中加入断点来检查某个时刻的脚本和变量状态。

要使用该功能,请在Unity Editor Status Bar的右下角将Code Optimization模式切换为Debug 或在Edit > Preferences > General > Code Optimization On Startup选项中将启动时的默认模式改为Debug模式。

Debug模式

你可以在代码编辑器中设定断点来让Debugger暂停运行:在需要设置断点的位置点击左侧侧边栏选项,或在右键菜单中进行选择。设置断点后,目标行的行数左侧会出现一个红圈(如下图)。

设置断点

在编辑器中选择Attach to Unity,然后在Unity编辑器中运行项目。

将Debugger整合至Unity

应用这时会在断点处暂停运行,让你有机会检查变量、检测是否有意外行为出现。

变量调试

如上方所示,你可以在调试时按步骤监测事件列表,检查脚本变量。

Debug控制按钮:Continue Execution(继续执行)、Step Over(跳过)、Step Into(进入)和Step Out(跳出)

你可以使用Continue Execution(继续执行)Step Over(跳过)Step Into(进入)Step Out(跳出)按钮来控制试运行流程。

Stop控制按钮

Stop按钮可停止/恢复代码运行。 

你也可以在Unity Player(运行版)中调试脚本代码。在构建Player前,请先在File > Build Settings中启用Development BuildScript Debugging两个选项。勾选Wait for Managed Debugger让Player在运行代码前加载Debugger。 要想将代码编辑器接入到Player,请先设定设备的IP地址(或设备名)和Player的端口,然后打开Visual Studio并启用Attach To Unity选项。

其他调试技巧

Unity提供的Debug类可显示出编辑器运行信息。你可以学习怎样在控制台打出消息或警告、在场景和游戏视图绘制示意线,或使用脚本来暂停编辑器的运行模式。此外还有一些其他技巧:

  1. Debug.Break可暂停代码运行。如果游戏的暂停时机难以把握,你可以使用该方法来暂停并检查某个值。  
  2. Debug.LogDebug.LogWarningDebug.LogError是在控制台显示消息的常用方法。Debug.Assert会在特定条件无法满足时输出讯息,但方法仅在有明确的UNITY_ASSERTIONS定义时才会生效。 在控制台中记录消息、警告和错误。  
  3. 你可以将某个对象传入Debug.Log来作为内容,点击这条消息,Unity将在层级视图中高光显示该对象。点击这条消息,Unity将在层级视图中高光显示该对象。  
  4. 你可以使用Rich Text文本来完善Debug.Log的消息,让错误报告更为清晰。  
  5. Unity不会自动剥离非开发版的Debug API。如果想要精简Debug相关的代码,你可以将Debug Log方法调用放到自定义的方法下,为其加上[Conditional]特性。 要想一次性编译出所有的Debug消息,请移除Player Settings下对应的Scripting Define Symbol,这一步类似于将Debug代码放到#if……#endif前处理器代码块中。 更多详情请查看这份优化指南。  
  6. 如果你想调试物理模拟,可以使用Debug.DrawLineDebug.DrawRay来可视化射线。

Debug.DrawLine

  1. 如果你仅想在Development Build中运行代码,可以检测Debug.isDebugBuild是否为真。  
  2. 你可以用Application.SetStackTraceLogType或Player Settings对应的选项来确定哪条控制台消息需要跟踪堆栈。堆栈跟踪信息有一定作用,但信息生成缓慢,还会产生垃圾数据。

自定义Console Log Entry(控制台消息行)

控制台的每条消息默认会显示两行信息,你可以将两行合并成一行来提高可读性,如下。你可以将两行合并成一行来提高可读性,如下图所示。

Console Log Entry选项

或者,你可以加上更多行让消息更长。

自定义编译器状态

Unity右下方的编译进度条不太容易被发现,你可以在编辑器脚本中调用EditorApplication.isCompling在编译期间生成一个悬浮窗来查看进度。在编译期间生成一个悬浮窗来查看进度。

使用MenuItem来初始化窗口,使用MenuItem来初始化窗口,你还可以用自己的GUIStyle来定制外观。

源码管理

Unity整合了两款版本控制系统:PerforcePlastic SCM。打开Player Settings > Editor,在Version Control一栏下配置服务器(Perforce还要求有证书)来添加版本控制服务器。

版本控制的项目配置。

Plastic SCM Cloud Edition免费提供5GB容量与三个席位。Plastic SCM可以同步所有的改动,并支持在Unity中直接查看项目修改历史。请在此处了解Plastic SCM的最新更新。

你也可以使用Git等第三方系统,也能用Git LFS(Large File Support)来高效地管理图像、音效等大型资源。 安装GitHub for Unity插件来享受GitHub托管服务器的便利,这款开源插件能让你在Unity中浏览修改历史、创建分支、提交改动并将代码推送至GitHub。

你还可以使用Unity的 .gitignore 文件来指明需要或不需要上传至代码库的文件,有选择地进行更新。

GitHub for Unity插件

Unity Teams是另一个辅助团队协作的选择。软件可将整个项目上传至云端,云端文件即可用作备份,也可四处分享,让项目的保存、分享和同步更为方便。

现在最新高生产力电子书

电子书

请在这里查看系列前两篇博文:5 ways to speed up your workflows in the EditorSpeed up your artist workflows。你也能下载Unity 2020 LTS使用指南,免费学习70多种提高效率、可操作性强的技巧。

如果你有其他想要了解的话题或内容,请在评论区留言,我们也欢迎大家签来分享你自己的高生产力技巧。

2021年9月27日 类别 Engine & platform | 10 分 阅读

Is this article helpful for you?

Thank you for your feedback!