优化篇
前言
本章节主要目的是学习记录游戏开发中各个模块里的优化知识,深入理解项目设计里的各种底层知识点,避免前期不考虑后期优化成灾的情况。
Note:
- 此处并不是要宣扬优化,项目初期不推崇过度优化毕竟产品做出来才是王道,而是通过深入理解核心知识点在项目初期做出正确的设计来避免没必要的后期优化。
UI模块
深入深度学习Unity UI(UGUI)模块的使用,优化,原理知识等。
UI基础
UI核心概念
Geometry is provided to Canvases by Canvas Renderer components.
从前面可以看出UGUI的绘制是以画布为单位的,子Canvas也就是嵌套的关系,大部分情况子Canvas脏了只会触发子Canvas的网格重建不会触发父Canvas的网格重建。
When composing user interfaces in Unity UI, keep in mind that all geometry drawn by a Canvas will be drawn in the Transparent queue.(UGUI的Canvas绘制实在Transpanrent Queue里)
A Graphic is a base class provided by the Unity UI C# library. It is the base class for all Unity UI C# classes that provide drawable geometry to the Canvas system. Most built-in Unity UI Graphics are implemented via the MaskableGraphic subclass, which allows them to be masked via the IMaskable interface.(UGUI里Graphic是提供Canvas里可绘制单位的基类,大部分UGUI组件继承至MaskableGraphic,为了支持Mask过滤。)
The updates of Layout and Graphic components is called a rebuild.(网格重建是因为排版或者Graphic组件有更新导致的,比如UI位置变化(排版),UI图片变化(组件变化))
- Batch Building Process(Canvases)
The batch building process is the process whereby a Canvas combines the meshes representing its UI elements and generates the appropriate rendering commands to send to Unity’s graphics pipeline. The results of this process are cached and reused until the Canvas is marked as dirty, which occurs whenever there is a change to one of its constituent meshes.(网格合并是为了将Canvas下的元素合并到一个网格数据里缓存起来直到UI被标记脏时。主要是为了减少DrawCall,减少GPU压力) - Rebuild Process(Graphics)
The Rebuild process is where the layout and meshes of Unity UI’s C# Graphic components are recalculated.(网格重建是因为Canvas下的UI有排版或者Graphic组件有变化触发的,目的是为了重新计算绘制所需的网格数据)
Whenever any drawable UI element on a given Canvas changes, the Canvas must re-run the batch building process. This process re-analyzes every drawable UI element on the Canvas, regardless of whether it has changed or not. (任何的可绘制UI变化都会导致Canvas重新执行网格合并,因为Mesh有变化了)
UI合批规则
UI顺序:
Unity UIs are constructed back-to-front, with objects’ order in the hierarchy determining their sort order.
UI是从后往前结合节点层级(Hierarchy)判定的出序列号的,相邻序列号的会检测是否能合批。所以我们要注意合批打断问题(比如相邻节点没有使用同一个图集,材质。相邻UI节点重叠问题等。)
详细学习参考:
Unity 之 UGUI 小总结
UI射线
UI射线响应需要满足下面几个条件:
- 目标UI是激活状态
- 点击区域是目标UI区域
- 目标UI对象本身或父节点有ICanvasRaycastFilter组件设置允许raycast
优化Raycast方案:
- 减少不必要的UI响应Raycast(关闭不必要的UI Raycast Target设置)
Note:
Unity 5.4之前有个Bug是即使没有input输入也会每帧检查Raycast造成额外开销。
常见问题
UI的几个常见问题如下:
- Excessive GPU fragment shader utilization (i.e. fill-rate overutilization)(过度使用GPU — 片元Shader的使用显示,比如填充率过高)
- Excessive CPU time spent rebuilding a Canvas batch(过度使用CPU — Canvas网格重建和合并)
- Excessive numbers of rebuilds of Canvas batches (over-dirtying)(过度高频率的触发Canvas网格重建和合并 — 比如大量的动态元素)
- Excessive CPU time spent generating vertices (usually from text)(过度的使用CPU — 生成过多的顶点数据,比如文本顶点数量)
从上面可以看出优化UI主要从两个方面下手:
- CPU(减少Canvas频繁的合并,减少生成过多的顶点数量)
- GPU(减少Drawcall和填充率)
Profile Tool
- Unity Profiler
- Unity Frame Debugger
- Xcode Intruments
- Xcode Frame Debugger
详情参考:
Unity UI Profiling Tools
优化建议
- 减少不可见UI — 比如全屏不透明UI显示时隐藏背后UI
- 简化UI结构 — 比如减少不必要节点 不要使用混合GameObject节点等
- 关闭不可见Camera — 比如全屏不透明UI显示时隐藏其他不必要Camera
- 划分多Canvas+动静分离 — 比如不同的窗口放到不同的Canvas下避免互相影响。动的元素放在一个Canvas下,静的元素放在一个Canvas下,避免动的元素影响静态元素的网格重建
- 使用最新版TextMeshPro来替换原生Text方案(TMP使用SDF技术支持不失真的动态字体大小变化)
Note:
- UGUI的Text的文字顶点绘制是单个文字就是一个独立的四边形网格(造成顶点数多)
- UGUI的Text动态字体对于不同的大小或者风格(粗体细体)是按不同的文字来处理的(容易造成Canvas的重绘(动态字体纹理重新生成))
- 文本变化是会触发网格重建和合并的(因为文本网格数据变化了)
实战
通过前面的学习,我们知道了UI的开销主要在Rebatch和Rebuild上。前者可以理解成通过UGUI合批规则把Canvas下的UI合并到指定数量的DrawCall传递到GPU去。后者可以理解成UI变化后重新计算Mesh。
UI优化的关键也就不言而喻了:
减少Rebatch
Canvas没有标记dirty或者Canvas下没有UI Mesh有变化时不会触发Rebatch。
这也就是为什么要划分Canvas且采用动静分离的原因,目的就是把经常变化的UI分离到单独的Canvas,减少静态UI部分的Rebatch开销。减少Rebuild
降低隐藏激活开销(这一点主要是对于UI显示状态变化时的一种优化)
根据UWA 六月直播季 | 6.29 Unity UI模块中的优化案例精讲的建议,UGUI最好采用Canvas Group设置Alpha为0的方式来避免SetActive带来的开销以及避免隐藏时的渲染开销
Note:
Unity 5.2版本Unity大力优化了UI Batch部分。
资源模块
资源分很多,比如纹理贴图,图集,材质,Shader,字体,音效,模型,动画等等等。接下来我会针对特定部分来学习针对性的优化知识点。
纹理资源
这里说的纹理资源同时也包含了图集,图集也可以理解成纹理的一种。
字体
待续……
音效
待续……
引用
Relative Study
Unity Conception Part
A guide to optimizing Unity UI
Fundamentals of Unity UI
Unity UI Profiling Tools
Fill-rate, Canvases and input
Optimizing UI Controls
Other UI Optimization Techniques and Tips