Unity 使用技巧
前言
掌握一些 Unity 编辑器的小技巧,会让你开发以及使用更加快捷有效。
正文
高亮选择
在 Scene 面板右上角的 Gizmo 下拉列表中,可以通过设置 Selection Outline 选项决定是否在选中物体时显示边缘高亮的标识。

Pixel Perfect Camera
在摄像机上挂载 Pixel Perfect Camera 组件能够使 2D 像素风格的游戏画面更加整洁清晰。此组件需要使用 Package Manager 安装 2D Pixel Perfect 包。

以 Y 轴为依据进行 Sprite 排序
对于 2D 游戏,将 Transparency Sort Mode (Edit > Project Settings > Graphics ) 设置为 Custom Axis,然后设置 Transparency Sort Axis,场景中的 Sprite 可以根据 Y 轴进行排序。如下图所示,当设置为(0,1,0)时,Y 坐标相对较大的 Sprite 排在 Y 坐标相对较小的 Sprite 之下,当设置为 (0,-1,0) 时,则相反。


延迟销毁游戏对象
默认情况下,使用 Destroy()方法会立即销毁游戏对象,如果想延迟一段时间再销毁,可在此方法中传递一个时间参数,如下:
1 | Destroy(gameObject,2f); |
快速新建基于自定义 Shader 的材质
在 Project 面板中选中一个自定义 Shader ,右键选择新建材质(Create>Material),则材质默认使用的着色器为 z 之前选择的 Shader,同时材质名称为 Shader 的名称。
脚本不挂载到游戏对象执行
通常情况下,新建的脚本要挂载到游戏对象上才能运行,如果在脚本中的方法前使用[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterSceneLoad)],可以不用挂载到任何游戏对象上即可在程序运行时执行此方法,方便在在程序初始化前做一些额外的初始化工作。如下代码所示:
1 | [] |
保存程序运行时组件属性的改变
在程序运行时改变组件的各属性值,当停止运行后,这些改变将重置为编辑状态下的数值,。程序运行时改变了组件的属性值,可以点击组件右上角的齿轮按钮,选择 Copy Component 命令,停止播放后,在相同的组件上,执行 Paste Component Value,从而能够保存在运行时对该组件做出的改变。
获取一个随机布尔值
我们知道 Random.value 能够返回 0~1 之间的随机数,所以让此随机数与 0.5f 进行比较,就能够获取一个随机的布尔值 True 或者 False,如下代码所示:
1 | bool trueOrFalse = (Random.value > 0.5f); |
使用 Struct 代替 Class
如果数据结构仅保存了有限的几个数值变量,可以考虑使用 struct 代替 Class,因为 Class 实例由垃圾回收机制来保证内存的回收处理; 而 struct 变量使用完后立即自动解除内存分配。
Visual Studio 自动语句补全
当使用 Visual Studio 进行代码编写时,可双击 Tab 键来辅助完成像 if、for、switch 等语句的补全。
协程嵌套
在一个协程里开启另外一个协程,可使用以下方法:
1 | void Start() |
脚本变量参与动画制作
使用工具还可以改变脚本的变量。
Animation 窗口快捷键
在 Animation 窗口中,按下 Ctrl+A,所有关键帧将集中显示在窗口中;选择某些关键帧,按下 F 键,可将它们居中显示在窗口中;按下 C 键,可以在曲线视图和关键帧视图间切换;按下 K 键添加关键帧。
反向播放动画
在 Animator 窗口中,设置动画的 Speed 属性为 - 1 可使动画片段反向播放。
快速比较距离
将两点之间的距离与一个固定距离进行比较时,可使两点相减然后取平方(即 sqrMagnitude),然后用该值与某个距离值的平方进行比较。不建议使用 Vector3.Distance 方法获取两点之间距离,然后与给定的距离值进行比较。因为 Vector3.Distance(a,b) 相当于 (a-b).magnitude,即求平方后开根,而 sqrMagnitude 方法省去了求平方根的操作,所以比 magnitude 执行快。
建议:
1 | if ((pointA - pointB).sqrMagnitude < dist * dist) |
不建议:
1 | if (Vector3.Distance(pointA, pointB) < dist) |
使用 TextMeshPro
使用 TextMeshPro 能够获得更多的文字控制自由度,并且能够有效防止文字边缘模糊。如下图所示,第一行文字通过 “Create > UI > Text” 命令创建,第二行文字通过 “Create > UI > TextMeshPro - Text” 命令创建。
在 Inspector 面板中显示私有变量
将私有变量标记为 SerializeField,可在 Inspector 面板中将其显示。
1 | [] |
在 Inspector 面板中隐藏公有变量
如果不希望在 Inspector 面板中显示公有变量,可将其标记为 [HideInInspector]。
1 | public int myNumber = 20; |
变量重命名后继续保持值
当变量重命名后,如果希望继续保留其数值,可使用 FormerlySerializedAs,如下代码所示:
1 | [] |
需要引用命名空间:
1 | using UnityEngine.Serialization; |
使用文件夹快捷方式
可将经常访问的文件夹的快捷方式拖入 Project 面板中,双击快捷方式可快速打开此目录。
F 与 Shift+F
选择游戏对象,按下 F 键,可将 Scene 的视口中央移动到该游戏对象处;按下 Shift+F,可将视口与该游戏对象锁定,即无论如何移动游戏对象,视口中央始终跟随此游戏对象。
对齐 Scene 与 Game 视图
在 Hierarchy 面板中选择摄像机,按下 Ctrl+Shift+F,可将摄像机移动到能够呈现 Scene 窗口中内容的位置。
CompareTag 方法
当对游戏对象的 Tag 进行比对时,从性能考虑,可使用 CompareTag 方法,不建议使用双等号进行判断。
建议:
1 | if (gameObject.CompareTag("Enemy")) |
不建议:
1 | if (gameObject.tag == "Enemy") |
使用空游戏对象作为分隔符
在 Hierarchy 面板中,可以使用名称中带有分隔符的空游戏对象进行组织管理。
查找含有某组件的游戏对象
如果需要查找挂载了某个组件的游戏对象,直接在 Hierarchy 面板的搜索框中输入组件名称即可,需要注意组件名称中的空格,比如搜索”MeshCollider“而不是”Mesh Collider“。
查找某种类型的资源
在 Project 面板中的搜索框中输入 “t:”+ 资源类型,可以过滤显示某种类型的资源,比如输入 “t:scene”,会过滤出所有场景文件,输入 “t:texture”,则会显示所有贴图。
移动代码行
在 Visual Studio 中,使用快捷键 Alt + 上下键,可以在代码块中快速上移 / 下移光标所在的代码行,不用复制粘贴。
快速查看组件文档
点击组件右上角的文档按钮,可快速打开关于当前组件的文档。建议下载离线文档,以便更加快速打开文档,如果没有下载,Unity 将打开在线文档。
文档版本历史
在 Unity 文档中点击 Documentation Version 链接,可查看不同版本的文档。
展开 / 折叠所有节点
在 Hierarchy 面板中,按下 Alt 键,鼠标左键点击树形节点,可展开 / 折叠当前节点下的所有子节点。
保存编辑器窗口布局
Unity 窗口布局可自定义,调整完毕以后,如果希望以后继续沿用此布局,点击编辑器右上角的 Layout 下拉列表,选择命令 Save Layout,可将当前窗口布局进行保存。
改变编辑器颜色
选择命令 Editor > Preferences 命令,可自定义编辑器当前主题的颜色。
修改 Playmode tint 的颜色值,可以改变编辑器在运行模式时的颜色,以提醒开发者此时为运行模式。
开关场景特效
在 Scene 面板顶部的图片下拉列表中,可选择开关某种类型的特效。
MenuItem 属性
要在编辑器的菜单栏中选择执行编写的函数,可在函数前添加 MenuItem 属性,如下代码所示:
1 | [] |

ContextMenu
使用 ContextMenu 属性标记函数,能够在脚本所在的上下文菜单中调用,如下代码所示:
1 | [] |

隐藏和锁定层
在编辑器右上角的 Layers 下拉列表中,点击对应层右侧的眼睛按钮,可以隐藏或显示某个层上的对象;点击锁按钮,可对某个层进行锁定或解锁,当被锁定后,该层上的所有对象将不能被选择。
层子菜单
当创建层时,使用斜杠符进行路径式命名可以为层添加子菜单,可以更好地组织项目。

使用 Scripting Define Symbols 定义脚本
在不同的目标平台下添加 Scripting Define Symbols(Project Settings > Player > Scripting Define Symbols),以分号分隔,可以将这些符号像使用 Unity 内置标签一样用作 #if 指令的条件。
颜色
在使用 Color 控件的滴管工具进行颜色选择时,可以拾取 Unity 编辑器之外的颜色。
在颜色属性之间也可以使用右键命令进行复制粘贴。
最大化窗口
使用快捷键 Shift + 空格键,可以快速最大化鼠标所在的窗口,而不用选择窗口右上角的 Maximize 命令
序列化 Struct 和 Class
在数据类型 Struct 和 Class 声明前使用 [System.Serializable],可以将其显示在 Inspector 面板中进行赋值。
碰撞矩阵
在 Edit > Project Settings… > Physics 中,通过设置 Layer Collision Matrix 可以决定能够互相碰撞的层。
Collider 相互作用矩阵
当两个对象发生碰撞时,会发送不同的碰撞事件,如 OnTriggerEnter、OnCollisionEnter 等等,这取决于具体的碰撞体设置,下表列出了不同类型的碰撞体发生碰撞时所能发出的事件类型。详情可参考 Unity 官方文档:https://docs.unity3d.com/Manual/CollidersOverview.html
数值输入
在 Inspector 面板中涉及到数值输入的字段,不仅可以直接输入数据,还可以在输入框中输入数学表达式,按下回车后 Unity 会将计算结果填充到输入框中。
锁定 Inspector
点击 Inspector 右上角的锁定按钮,或在上下文菜单中选择 Lock 命令,可以将当前选中游戏对象的 Inspector 面板锁定。然后选择 Add Tab > Inspector 命令,添加一个 Inspector,这样能够方便在两个游戏对象之间互相拷贝组件数据。
Inspector 调试模式
在 Inspector 面板右上角的下拉菜单中,选择 Debug 命令,启动调试模式,此时将显示组件包含的所有变量,包括私有变量,当运行编辑器时,可以实时查看各组件所有变量的变化。
高亮显示 Debug.Log 对应的游戏对象
当使用 Debug.Log 方法输出信息时,可将 gameObject 作为此方法的第二个参数,当程序运行时,点击 Console 面板中对应的输出信息,可在 Hierarchy 面板中高亮显示挂载了此脚本的游戏对象。
1 | void Start() |

风格化 Debug.Log 的输出信息
当 Debug.Log 方法的输出消息是字符串时,可以使用富文本标记来强调内容。如下代码所示:
1 | Debug.Log("<color=red>Fatal error:</color> AssetBundle not found"); |
输出效果:
绘制调试数据
当变量随着时间的推进而改变时,可使用 AnimationCurve 实例在程序运行时绘制此数据,如下代码所示:
1 | public AnimationCurve plot = new AnimationCurve(); |
返回 Unity 编辑器,运行程序,点击 plot 属性,此时会随着时间动态绘制数据的变化情况,如下图所示:

快速新建脚本并挂载到游戏对象上
选择游戏对象,在 Inspector 面板上点击 Add Component 按钮,在搜索框中输入新建的脚本名称并回车,可新建脚本并挂载到目标游戏对象上,双击脚本名称进行脚本编写。
导入第三方项目文件
Unity 能够读取部分第三方创作工具保存的项目文件,比如 Photoshop 的 PSD,Blender 的源文件等,不需要从这些软件导出中转文件格式,比如 Jpg、FBX 等。
导入后保留 PSD 文件的图层结构
将 PSD 文件另存为 PSB 格式,将其导入 Unity 后可保留文件图层结构,此时需要在 Package Manager 中安装 2D PSD Importer,并且在文件的导入属性中设置 Texture Type 为 Sprite (2D and UI)。
为游戏对象指定 / 自定义图标
点击游戏对象 Inspector 面板左上角的下拉菜单,可为游戏对象指定一个特定颜色的标识,这对空游戏对象的可视化也比较有用。点击 Other… 按钮,可以用自己的图片来进行标识。
显示 / 隐藏 Gizmo
点击 Scene 面板右上角的 Gizmo 下拉列表,可以选择显示或隐藏某类组件的图标和 Gizmo 标识;也可点击 Game 面板右上角的 Gizmo 按钮,显示或隐藏所有资源的图标和 Gizmo。
字符串拼接
可使用 StringBuilder 进行字符串的拼接,不要使用字符串相加的形式,因为这样会带来额外的内存垃圾。如下代码所示:
1 | StringBuilder myStr = new StringBuilder(); |
不建议:
1 | string myStr = "Hello" + "the" + "world"; |
使用 StringBuilder 需要引用命名空间 System.Text。
使用 ScriptableObjects 管理游戏数据
对于游戏数据比如武器、成就等,可使用 ScriptableObjects 在编辑器中进行有效组织。如下代码所示:
1 | using UnityEngine; |

编辑器播放时修改脚本后的处理
选择 Edit > Preferences > General 命令,在 Script Changes While Playing 中,可以设置编辑器在播放状态下如果脚本发生改变后的处理,比如停止播放重新编译等。
自定义窗口
将类继承自 EditorWindow,可以添加自定义窗口,在此基础上编写一些命令和工具,如下代码所示:
1 | using UnityEngine; |
执行效果:

自定义 Inspector
也可对 Inspector 进行自定义,添加一些控件。如下代码所示:
1 | using UnityEngine; |
执行效果:
工具快捷键
使用快捷键 Q、W、E、R、T、Y 切换移动、旋转、缩放等工具。
使用 RectTransform 工具缩放 3D 物体
RectTransform 工具一般用于缩放 2D 物体,对 3D 物体使用该工具可以在某个二维平面对其进行缩放,这取决于物体与视口的关系。
吸附
按下 Ctrl 键对游戏对象进行移动、旋转、缩放,将以步进的形式进行操作,选择 Editor > Snap Settings… 命令,可设置步进大小。
按下 V 键,在游戏对象上选择顶点进行拖放,将以此顶点为基础,把游戏对象吸附到其它顶点的位置。
管理程序集
在 Project 面板中选择 Create > Assembly Definition 命令,创建程序集文件,然后将其拖放到指定的文件夹中,定义脚本依赖关系,可以确保脚本更改后,只会重新生成必需的程序集,从而减少编译时间。
WaitForSecondsRealtime
当时间缩放为 0 时(即 Time.timeScale=0f),waitForSeconds 方法将不会停止等待,后续代码也不会执行,此时可使用 WaitForSecondsRealtime 方法,如下代码所示:
1 | Time.timeScale = 0f; |
缓存组件引用
当某组件需要被频繁访问时,可在初始化时预先获取该组件的引用,从而避免在访问时由于重复获取引起的性能开销。
1 | private Rigidbody rb; |
同样的情况,也不要在使用 Camera.main 获取摄像机组件,尤其避免使用类似以下方法:
1 | Camera cam = GameObject.FindGameObjectWithTag("MainCamera").GetComponent<Camera>(); |
这样会带来更大的性能消耗。
字符串性能优化
如果某字符串在整个应用过程中不会改变且被频繁使用,可将其存储在静态只读变量中,从而节省内存分配,如下代码所示:
1 | static readonly string Fire1 = "Fire1"; |
不建议:
1 | void Update() |
方便使用的元数据
为变量添加一些属性可使它们在 Inspector 面板中更容易被使用。在变量前添加 Range 属性可将其限定在某个范围内使用滑块进行调节,如下代码所示:
1 | [] |
执行效果:
两个变量声明之间加入 [Space]可在 Inspector 中添加一个空行;添加 Header 可在 Inspector 面板中加入一段文字,如下代码所示:
1 | public float speed = 1f; |
执行效果:
在变量前加入 Tooltip,当鼠标悬停在 Inspector 面板中的变量上时,可显示关于此变量的说明,如下代码所示:
1 | [] |
执行效果:
在 Unit 编辑器中访问 Asset Store
Asset Store 可在 Unity 编辑器和网页浏览器中访问。(此条有充数嫌疑)
合并场景
在 Project 面板中,将一个场景文件拖到另外一个上,可将场景进行合并。
创建游戏对象 / 数组元素副本快捷键
选择一个游戏对象,使用快捷键 Ctrl+D 可快速创建该游戏对象的副本,同样的方法可创建数组元素的副本。
组件预设
当完成某个组件的属性设置后,可点击组件右上角的预设按钮,将当前属性设置保存为预设,方便后续进行组件设置时使用。
遍历游戏对象所有子物体
可使用 foreach 循环遍历游戏对象的所有子物体,如下代码所示:
1 | foreach (Transform child in transform) |
通过脚本改变游戏对象在 Hierarchy 中的顺序
使用 transform.SetSiblingIndex 方法可以设置游戏对象在 Hierarchy 面板中的顺序,如下代码所示:
1 | transform.SetSiblingIndex(1); |
以上代码实现在游戏运行时,设置游戏对象在 Hierarchy 面板中的顺序为同级节点中的第二个。
保存选择状态
当选择了多个游戏对象后,可在 Edit > Selection 的子菜单中选择一个 Save Selection 项,暂存当前选择状态。选择 Load Selection + 对应的序号,即可恢复某个选择状态。此方法对跨节点选择多个对象的情况非常适用,这样将不必依次展开节点重新进行查找选择。
#region 和 #endregion
使用 #region 和 #endregion 可以将两者之间包含的代码折叠,方便阅读。
通过脚本暂定编辑器播放
使用 EditorApplication.isPaused 可通过代码在编辑器播放时将其暂停,如下代码所示:
1 | void Update() |
需要引用命名空间 UnityEditor。
逐帧查看程序运行
点击暂停按钮右侧的步进(Step)按钮,可以在程序运行时逐帧查看程序运行状态。
查看游戏性能统计
点击 Game 窗口右上角的 Stats 按钮可以查看游戏性能统计数据,如帧率、批处理等指标。
查看更加详细的分析数据,可使用 Window > Analysis > Profiler 工具;使用 Profiler.BeginSample 和 Profiler.EndSample 方法可在 Profiler 中查看函数的资源使用情况,如下代码所示:
1 | Profiler.BeginSample("expensive"); |
需要引入 UnityEngine.Profiling 命名空间。
弹出预览窗口
通常情况下,项目资源在 Inspector 面板底部均有一个预览窗口。鼠标右键点击预览窗口顶部,可将该窗口弹出,作为独立窗口,放置在编辑器的任意位置。
测试游戏时静音
点击 Game 窗口右上角的 Mute Audio 按钮,可在编辑器播放时将所有声音关闭。
InvokeRepeating 方法
InvokeRepeating 能够按照一定的时间间隔反复执行某个函数,若不使用 CancelInvoke 方法,InvokeRepeating 将持续执行,即使将方法所在的脚本关闭。
Frame Debugger
使用 Frame Debugger(Window > Analysis > Frame Debugger)可以查看每一帧的渲染过程。
Physics Debugger
使用 Physics Debugger(Window > Analysis > Physics Debugger)可以查看碰撞引起的异常,当开启 Collision Geometry 选项后,场景中所有游戏对象的碰撞体都将被绘制出来,而不用依次选择游戏对象进行检查。如下图所示,球体因为添加了不正确的 Box Collider,在物理碰撞时必然不能达到预期的表现效果。
to be continued…