Unity UI 优化建议,对官方文档的理解性翻译 (二)

3.Unity UI Profiling Tools - UI 调试工具

There are several profiling tools useful for analyzing Unity UI’s performance. The key tools are:

  • Unity Profiler
  • Unity Frame Debugger
  • Xcode’s Instruments or Intel VTune
  • Xcode’s Frame Debugger or Intel GPA

列出了两个Unit相关工具,两个XCode相关工具。XCode相关的就先不看了只贴出原文,以后有需要再说。

The external tools provide method-level CPU profiling with millisecond (or better) resolution, as well as detailed draw-call and shader profiling. Instructions for setting up and using the above tools lie beyond the scope of this guide. Note that the XCode Frame Debugger and Instruments are only usable on IL2CPP builds for Apple platforms, and therefore can currently only be used to profile iOS builds.

这里就是说XCode只支持IOS并且需要IL2CPP编译,XCode拥有更详细更底层的运行信息。

Unity Profiler

The primary use for the Unity Profiler is to perform comparative profiling: enabling and disabling elements of a UI while the Unity Profiler is running can quickly narrow down the portions of a UI hierarchy that are most responsible for performance issues.

To analyze this, watch the Canvas.BuildBatch and Canvas.SendWillRenderCanvases lines in the profiler’s output.

Unity Profiler的主要用途是进行比较分析:在Unity Profiler运行时,启用和禁用UI元素可以快速缩小范围,找到UI层次结构中对性能影响最大的部分。要分析这一点,请观察Canvas.BuildBatch和Canvas.SendWillRenderCanvases。

Canvas.BuildBatch is the native-code calculations that perform the Canvas Batch Building process, as described previously.

Canvas.BuildBatch是进行Canvas合批计算的本机代码,就像前文说的一样。

Canvas.SendWillRenderCanvases contains the invocation of the C# scripts that are subscribed to the Canvas component’s willRenderCanvases Event. Unity UI’s CanvasUpdateRegistry class receives this event and uses it to run the Rebuild process, described previously. It is expected that any dirty UI components will update their Canvas Renderers at this time.

Canvas.SendWillRenderCanvases包含对那些监听了willRenderCanvases 事件的C#代码的调用。Unity UI的CanvasUpdateRegistry类接收这个事件并使用它来运行前面描述的重绘过程。预计所有标记为dirty的UI组件都会在此时更新他们的Canvas Renderers。

Note: To more easily see differences in UI performance, it is generally advisable to disable all of the trace categories aside from “Rendering”, “Scripts” and “UI”. This can be done by clicking on the colored boxes beside the name of the trace category on the left-hand side of the CPU Usage profiler. The categories can also be re-ordered in the CPU profiler by clicking and dragging the names of the categories upwards or downwards.

注意:为了更容易地看到UI性能上的差异,通常建议禁用除“Rendering”、“Scripts”和“UI”之外的所有跟踪类别。这可以通过单击CPU使用率分析器左侧跟踪类别名称旁边的彩色框来实现。还可以直接通过单击和拖动类别的名称来重新排序。

The UI category is new in Unity 2017.1 and up. Unfortunately, parts of the UI update process are not categorized correctly, so be careful when looking at the UI curve because it may not contain all UI related calls. For example, Canvas.SendWillRenderCanvases is categorized as "UI", but Canvas.BuildBatch is categorized as “Others” and “Rendering”.

在Unity 2017.1和更高版本有了UI这一类。不幸的是,部分UI更新过程没有被正确地分类,所以在查看UI曲线时要小心,因为它可能不包含所有与UI相关的调用。例如, Canvas.SendWillRenderCanvases 被归类为“UI”,但是Canvas.BuildBatch被归类为“Others”和“Rendering”

In 2017.1 and up, there’s also a new UI Profiler. By default, this profiler is the last one in the Profiler window. It consists of two timelines and a batch viewer:

UI分组默认在Profiler窗口的最后,它由两个时间轴和一个合批查看器组成

The first timeline shows the CPU time spent in two categories, respectively computing layout and rendering. Note that it suffers from the same problem described previously and some UI functions may not be accounted for.

第一个时间轴显示了CPU花在布局(layout)和渲染(render)上的时间。请注意,它和前面的描述有相同的问题,有些UI方法可能看不到。

The second timeline shows the total number of batches, vertices and also displays event markers. In the previous screenshot, you can see a couple of button click events. These markers can help you determine what caused a CPU spike.

第二个时间轴显示合批的数量、顶点数和事件标记。在前面的屏幕截图中,您可以看到几个按钮单击事件。这些标记可以帮助您确定导致CPU峰值的原因。

Finally, the most useful feature of the UI Profiler is the batch viewer at the bottom. On the left, there’s a tree view of all your canvases and underneath each of them, a list of the batches they generated. The columns provide interesting details about each canvas or batch, but there’s one in particular that is crucial to better understand how to optimize your UI and it’s the Batch Breaking Reason.

最后,UI分析器最有用的特性是底部的合批查看器。在左边,有一个所有Canvas的树状图,在每个Canvas的下面,是它们生成的合批的列表。这些列提供了关于每个Canvas或合批的有用的细节,其中有一个对于更好地理解如何优化UI至关重要,那就是Batch Breaking Reason(合批中断的原因)。

This column will show why the selected batch couldn’t be merged with the previous one. Reducing the number of batches is one of the most effective way of improving UI performance, so it’s important to understand what breaks batching.

这一列将说明为什么所选的合批不能与前一个合批合并。减少合批的数量是提高UI性能的最有效的方法之一,因此了解是什么打破了合批非常重要。

One of the most frequent reason, as shown in the screenshot, is a UI element using a different texture or material. In many cases, this can easily be fixed by using sprite atlases. The last column shows the name of the game objects associated with the batch. You can double click on the name to select the game object in the editor (this is particularly helpful when you have several objects with the same name).

如截图所示,最常见的原因之一是UI元素使用了不同的贴图或材质球。在许多情况下,可以通过使用sprite图集轻松地解决这个问题。最后一列显示与合批相关的游戏对象的名称。您可以双击名称来在编辑器中选择游戏对象。

As of Unity 2017.3, the batch viewer only works in the editor. The batching should usually be the same on device, so this is still really helpful. If you have doubt that batches may be different on device, then you can use the Frame Debugger that will be described next.

在Unity 2017.3中,合批看器只在编辑器中工作。真机设备和编辑器看到的值通常来说是一样的。如果您怀疑设备上的合批可能不同,那么您可以使用下面将介绍的 Frame Debugger。

Unity Frame Debugger

The Unity Frame Debugger is a useful tool for reducing the number of draw calls generated by a Unity UI. This built-in tool can be accessed via the Window menu within the Unity Editor. When enabled, it will display all draw calls generated by Unity, including those generated by Unity UI.

在我们想要给UI降低drawcalls时,Unity Frame Debugger是一个非常有用的工具。这个内置的工具可以通过Unity编辑器中的 Window 菜单来打开。当启用时,它将显示所有由Unity(包括UI)生成的 drawcalls。

Notably, the frame debugger will update itself with the draw calls generated to display the Game View in the Unity Editor, and therefore can be used to try out different UI configurations without even entering Play Mode.

frame debugger显示drawcalls靠的是编辑器中的Game窗口,因此可以直接在编辑模式下尝试各种UI组合而不一定非要运行。

The location of the Unity UI draw calls depends on the Render Mode selected on the Canvas component being drawn:

  • Screen Space – Overlay will appear within Canvas.RenderOverlays group
  • Screen Space – Camera will appear within the Camera.Render group of the selected Render Camera, as a subgroup of Render.TransparentGeometry
  • World Space will appear as a subgroup of Render.TransparentGeometry for each World Space camera in which the Canvas is visible

Drawcalls的时机和Canvas选择的渲染模式(Render Mode)有关:

  • Screen Space – Overlay 会显示在 Canvas.RenderOverlays分组中
  • Screen Space – Camera 会显示在 Camera.Render分组中所选相机的 Render.TransparentGeometry子分组中
  • World Space 会出现在所有能看到这个Canvas的世界中的相机的Render.TransparentGeometry子分组中

All UIs can be identified by the “Shader: UI/Default” line (assuming that the UI shader has not been replaced with a custom shader). in the group or draw call’s details. See the highlighted red boxes in the below screenshot.

所有的UI都可以通过“Shader: UI/Default”行来识别(假设UI shader没有被自定义shader替换)。如下屏幕截图中高亮显示的红色方框,可以看到分组和drawcall的细节。

By watching this set of lines while tweaking a UI, it is relatively simple to maximize the Canvas’ ability to combine UI elements into batches. The most common design-related cause of broken batches is unintentional overlap.

通过在调整UI时观察这组数据,可以相对简单地使Canvas将UI元素合批的能力发挥极致。最常见的因设计导致的合批中断原因是不小心的重叠。

All Unity UI components generate their geometry as a series of quads. However, many UI sprites or UI text glyphs occupy only a fraction of the quads used to represent them, with the rest being empty space. As a result, it is quite common to find that the UI’s designer has unintentionally overlapped multiple different quads whose textures come from different materials and therefore cannot be batched.

所有的Unity UI组件都是通过一系列的quad来生成它们的图形。然而,许多UI sprites或UI text 只占用用于表示它们的quad中的一小部分,其余部分是空白。因此,经常会发现UI设计师无意中重叠了多个不同的quad,它们的贴图来自不同的材质球,因此无法成批处理。

As Unity UI operates entirely in the transparent queue, any quads that have unbatchable quads overlaid atop them must be drawn before the unbatchable quads, and therefore cannot be batched with other quads placed atop the unbatchable quads.

因为Unity UI完全是在透明队列中运行的,(这TM是绕口令么)意思就是本来可以合批的一些quad,如果中间插入了一些不可合批的quad,由于透明渲染方式为从后向前,所以这些本应该可以合批的quad必须等待中间插入的这些玩意先绘制,因此打断了自己的合批。

Consider a case of three quads, A, B, and C. Assume all three quads overlap one another, and also assume quads A and C use the same material while quad B uses a separate material. Quad B therefore cannot be batched with A or C.

举个例子,现在有A,B,C三个quad,A和C使用相同的材质球,而B不是。所以B无法和A或C合批。

If the order in the hierarchy (from top to bottom) is A, B, C then A and C cannot be batched, because B must be drawn atop A and beneath C. However, if B is placed before or after the batchable quads, then the batchable quads can actually be batched – B needs only to be drawn before or after the batched quads and does not interpose them.

如果在hierarchy 中的顺序为A,B,C,那么A和C也无法合批。因为B必须在A和C之间进行绘制。如果把B放在A的上面或者C的下面,那么AC就可以合批了,B不会打断他们。

For further discussion of this issue, see the Child order section of the Canvas step.

关于这个问题的进一步讨论,请看Canvas step章节的Child order部分

Instruments & VTune

Xcode Frame Debugger & Intel GPA

这两块讲的是XCode相关的,以后用到了再看。

Analyzing profiler results - 分析调试结果

After gathering profiling data, several conclusions might be drawn. If Canvas.BuildBatch or Canvas::UpdateBatches seems to be using an excessive amount of CPU time, then the likely problem is an excessive number of Canvas Renderer components on a single Canvas. See the Splitting Canvases section of the Canvas step.

在收集了分析数据之后,可以得出几个结论。如果Canvas.BuildBatch 或Canvas::UpdateBatches似乎使用了过多的CPU时间,那么可能的问题是在单个Canvas上使用了过多的Canvas Renderer 组件。请参阅Canvas step章节的 Splitting Canvases部分。

If an excessive amount of time is spent drawing the UI on the GPU, and the frame debugger indicates that the fragment shader pipeline is the bottleneck, then the UI is likely exceeding the pixel fill rate which the GPU is capable of. The most likely cause is excessive UI overdraw. See the Remediating fill-rate issues section of the Fill-rate, Canvases and input step.

如果在GPU上绘制UI的时间过多,并且frame debugger指出片段着色器管线是瓶颈,那么UI很可能是超出了GPU的像素填充率。最可能的原因是UI overdraw。请参阅 Fill-rate, Canvases and input章节的Remediating fill-rate issues部分。

If Graphic Rebuilds are using excessive CPU, as seen by a large portion of CPU time going to Canvas.SendWillRenderCanvases or Canvas::SendWillRenderCanvases, then deeper analysis is needed. Some portion of the Graphic Rebuild process is likely responsible.

如果Graphic Rebuilds使用过多的CPU,并且看到大部分CPU时间用在Canvas.SendWillRenderCanvases 或Canvas::SendWillRenderCanvases,则需要更深入的分析是Graphic Rebuild过程中的哪部分造成的。

In the case that a large portion of WillRenderCanvas is spent inside IndexedSet_Sort or CanvasUpdateRegistry_SortLayoutList, then time is being spent sorting the list of dirty Layout components. Consider reducing the number of Layout components on the Canvas. See Replacing layouts with RectTransforms and Splitting Canvases sections for possible remediations.

如果WillRenderCanvas的很大一部分时间是在IndexedSet_Sort或CanvasUpdateRegistry_SortLayoutList中花费的,那么就是Layout 组件在对dirty排序。考虑减少Canvas上Layout 组件的数量。请参阅Replacing layouts with RectTransforms and Splitting Canvases章节。

If excessive time seems to be spent in Text_OnPopulateMesh, then the culprit is simply the generation of text meshes. See the Best Fit and Disabling Canvases sections for possible remediations, and consider the advice inside Splitting Canvases if much of the text being rebuilt is not actually having its underlying string data changed.

如果过多的时间花费在Text_OnPopulateMesh上,那么罪魁祸首就是文本网格的生成。请参阅Best Fit and Disabling Canvases章节,如果正在重绘的大部分文本实际上并没有文字上的改变,请参考 Splitting Canvases(就是拆分Canvas)。

If time is spent inside Shadow_ModifyMesh or Outline_ModifyMesh (or any other implementation of ModifyMesh), then the problem is excessive time spent calculating mesh modifiers. Consider removing these components and achieving their visual effect via static images.

如果在Shadow_ModifyMesh或Outline_ModifyMesh(或ModifyMesh的任何其他实现)中花费了时间,那么问题就是计算网格变化的时间过多了。考虑删除这些组件,并通过静态图像实现它们的视觉效果。

If there is no particular hotspot within Canvas.SendWillRenderCanvases, or it appears to be running every frame, then the problem is likely that dynamic elements have been grouped together with static elements and are forcing the entire Canvas to rebuild too frequently. See the Splitting Canvases step.

如果Canvas.SendWillRenderCanvases没有出现特定的峰值,或者它似乎每一帧消耗的性能差不多高,那么问题可能是动态元素与静态元素组合在一起,迫使整个画布过于频繁地重绘。请看Splitting Canvases章节

发布了13 篇原创文章 · 获赞 1 · 访问量 434

猜你喜欢

转载自blog.csdn.net/u011366226/article/details/104578778