Unity GUI (Ugui) Usage tips and Performance summary

Source: Internet
Author: User
Tags unity 5
Background and purpose

Little Kazakhstan Contact Unity3d also has a period of time, the project team in the UI solution selection has been used in the original Ugui, so I also used a period of time Ugui, in the use of Ugui accumulated some of their own experience, here to make a record and summary.

This article will focus on the runtime performance of Ugui, other factors are also many and very important, but an article to clear one thing is good, the text will provide Ugui best practice and some use skills, do not want to see the full text of the recommendations directly to the bottom of the Jay, Ah, No, it's a conclusion. factors affecting the performance of Ugui and inspection tools

The UI in the game is essentially the same as other elements in the game, and the opposite is that theUI is usually composed of 2D images, which contain more transparent elements and gradient elements, and generally appear at the top of the screen .

Thus, in common terms, the runtime performance consumption of the UI can also be divided into CPU consumption, GPU consumption, and memory consumption. For each part of the specific consumption and optimization, there are many great gods on the Web published articles, such as in-depth chat Unity3d project optimization: From draw calls to GC. However, there is always a point that everyone can not open, that is, the number of Drawcall,drawcall directly affect the game frame rate, solve the drawcall problem, it should be considered to solve the problem of 80%, so the next focus on the characteristics of Ugui to talk about the UI system Drawcall.

Unity 5.0 has a very useful tool for drawcall viewing, Frame Debugger, opened by [Window->frame Debugger].
Frame Debugger (only in unity5.0+)


When you use the tool, the game pauses, and unity caches the contents of the currently executing frame, where all drawcall you can move forward and backward, allowing you to analyze the overhead from the drawcall level. So there is no upgrade to 5.0 of the small partners hurriedly upgrade AH.

In addition, when using FD to look at UI performance, a little trick is to open an empty scene, and then drag your UI prefab into the empty scenes, this time will not be affected by other objects in the scene and only show the UI Drawcall. Ugui Performance Optimization

Having spoken so much, I began to get to the chase.
A very important concept in reducing drawcall is batch, because once Drawcall is equivalent to the cost of a CPU-to-GPU communication, and if the CPU can package more information to the GPU at once, then the number of Drawcall is naturally down, The process of packaging the transfer of information to the GPU is called batch, batch processing. So under what circumstances can this information be packaged? from Ugui's point of view, if the components in your UI are the same material and texture, these components can be batch. In the image component, the material corresponds to the source Image, the texture corresponds to the material, and the texture to the font in the text component, which is also material. The above corresponds to most of the circumstances applicable, in a small number of special shader will fail (to be further studied).
Common UI Components


That's the way it works, but it takes some skill to actually use it and follow the rules of some of Unity's rendering order to truly optimize performance. Here's a discussion. Package Atlas

The above refers to the source image atlas, so-called Atlas, is a lot of fragmented 2D small images through Unity's own sprite Packer or third-party texture Packer merged into a large image, so there are several advantages, the image size of 2 recurses, GPU processing will be much faster, the small map itself is not able to do every picture is 2 power, but to make a large picture can (waste a bit of it does not matter); When the CPU transmits the resource information to the GPU, it only needs to pass a large image, because the GPU can be sampled in different areas of the graph, And then spell out the corresponding interface. Note that this is why it is necessary to use the same source image Atlas, which is the key to batch, because a drawcall will pass all the raw material, GPU you draw it.

But obviously it is unreasonable to make all the pictures into a picture set, because this picture may be very large, so it is necessary to classify the images according to certain rules. In the classification of ideas, we want to do drawcall as little as possible, while the amount of resources also as little as possible (more reuse), but the two are mutually exclusive, so a compromise, you can follow the following ideas: Design UI to consider reusability, such as some borders, buttons, etc., as a shared resource, placed in 1~ 3 large atlas, called re -use Atlas; other non-reusable UI is divided by function module, each module uses one or three Atlas, as a function Atlas ; for some UIs, if you use both a feature Atlas and a reuse Atlas , However, there are more "vacancies" in the functional Atlas , so you can consider using the elements in the reuse Atlas to separate them into the feature Atlas, so that the UI depends only on the feature Atlas. That is, through a certain amount of redundancy, to achieve performance improvement.

P.S. If you use Unity's own sprite Packer to pack the atlas, you may want to see the effect in run mode. Unity GUI-level merge rules and batch generation rules

The stacking order of the Ugui is carried out from top to bottom in the order of hierarchy, that is, the more up-to-the-top components are drawn on the lower end. So that's how the UI stacks up and down the floor. Of course such a plot efficiency is certainly unacceptable, so to merge, to batch,unity itself provides an algorithm to decide which layers should be merged together and in what order to draw. The batch UI elements for all adjacent layers will be completed in one Drawcall . The next step is to discuss Unity's hierarchical merging and computing algorithms.

Unity's UI rendering order is determined in 2 steps, with the first step calculating the hierarchy number of each UI element, and the second merging elements in the same hierarchy that can be batch as a batch , and the batch to sort;

The algorithm for calculating the hierarchy number is explained from an intuitive perspective: if there is a UI element that occupies a screen range (usually a rectangle), if there is no UI underneath it, then its hierarchy number is 0 (bottom) If there is a UI underneath it and the UI can and it batch, it has the same level number as the bottom UI level, and if there is a UI underneath it but cannot batch with it, its hierarchy number is the bottom level of the UI + 1; If there are more than one UI underneath it, then iterate through all the hierarchy numbers in the first two ways, with the largest one as their own hierarchy number .

Here is also a pseudo-code, assuming that all UI elements (discard hierarchies) are loaded from the top down in a list, then each UI element corresponding to the level number calculation can refer to the following:

function Callayer (List uielelst) if (Uielelst.count = = 0) return;
  Initial the first UI Element as layer 0 uielelst[0].layer = 0; 
    for (i = 1 ~ uielelst.count) {var iscollidewithelements = false; Compare with all elements beneath for (j = i-1 to 0) {//if element-i collide with Element-j If (Uielelst[i] . Rect.collidewith (Uielelst[j].
        Rect) {iscollidewithelements = true; If Element-i can is batched with element-j, same layer as Element-j if (Uielelst[i].
        Qualifytobatchwith (Uielelst[j])) {uielelst[i].layer = Uielelst[j].layer;
        } else{//or else the layer is larger Uielelst[i].layer = Uielelst[j].layer + 1; }}}//if not collide with any elements beneath, set layer to 0 If (!
    iscollidewithelements) {uielelst[i].layer = 0; }
  }

With the hierarchy number, the batch is merged , and Unity will sort all the elements of each layer (by material, texture, and so on), merge the elements that can be batch into a batch , and the currently known collation is, The text component is rendered before the image component , while the collation of the same class of components is unknown (as if there were no rules). after the above sort, we can get an ordered batch sequence . At this point,unity will make another optimization, that is, if the two batches in the adjacent room can be batch, then batch willbe done. For a chestnut, a imagea with a level of 0, a imageb with a level of 1 (2 image batches) and a textc,unity with a hierarchy of 0 sorted Textc->imagea->imageb, and the latter two batches can be merged , so it is 2 drawcall. Another chestnut, a 0-level TEXTD, a 1-level texte (2 text-to-batch) and a 0-level imagef,unity sorted batch of Textd->imagef->texte, This will require 3 drawcall. (Not a bit dizzy, and then look at the bold word)

The following pseudo-code some lazy, really lazy to write sort, merge and so on, a long string is not good to read, a few steps listed, other people look at the above paragraph of the word brain fill it ...

function Mergebatch (List uielelst) {//order The UI Elements by their layers and batch-keys,//batch-key is a combin  ation of its component type,//texture and material info Uielelst.orderby (uiElement) =>{return this.layer > Uielement.layer | | This.

  Batchkey () > Uielement.batchkey ()});

  Merge the UI Elements with same layer and batch-key as a batch var batchlst = Uielelst.mergesameelementsasbatch ();

  Make adjacent batches with same Batch-key merged batchlst.mergeadjacentbatches ();
return batchlst; }

According to the above rules, you can get some "pendulum UI" skills: the same texture and texture of the UI elements can be batch, the batch UI can be stacked on a piece does not affect performance, but if the UI elements can not be stacked in batch, it will increase the drawcall overhead. To pay attention to the cascading relationship between UI elements, it is recommended to use the "T" tool to see its rectangle size, because some of the pictures are transparent, but stacked on top of the other UI, and then not batch, there will be no reason to many drawcall; the most visible UI is the image and text component, When text is stacked on top of the image (such as a button), and then a picture is stacked on the text, there will be at least 2 more drawcall, consider printing the font directly on the image below, and in some cases consider artificially increasing the hierarchy to reduce drawcall, For example, a text hierarchy of 0, another batch of text stacked on a picture A, Level 1, then 2 text because the hierarchy will be arranged 2 drawcall, but if a transparent picture in the first text (with picture a can be batch), The two-text hierarchy is the same, drawcall can be reduced by one. Use mask less

Mask is a nightmare for Ugui performance, because it is likely that the number of drawcall increases exponentially as a result of this thing.

The specific principle of the mask implementation is a drawcall to create a stencil mask (to do pixel culling), then draw all the child UI, and then remove the stencil mask in the last Drawcall. This two drawcall can not be compared with other UI operations to batch, so the surface to add a mask will be more than 2 drawcall, but, because the mask is similar to the "hamburger-like" rendering order, all mask child nodes and other UI is actually in two worlds, The hierarchical merge rules mentioned above can only be used for these two worlds, so many UI that could have been merged could not be merged.

Therefore, when using Ugui, there are some suggestions: should try to avoid the use of mask, in fact, the mask function can be implemented in some cases, such as the design of a border, so that the border is stacked on the top, the bottom of the UI when moving, it will be obscured by this frame, if you want to use mask, You need to evaluate the performance loss of the mask and minimize it. For example, if the UI inside the mask is dynamically generated (such as a list component), you need to be aware of the overlap between the UI. Summary

Ugui performance in fact involves a lot of, listed here is only now can think of, because personal ability is limited, there may be some flaws. For some of the suggestions in this article, here are some best practices: Consider reusability when designing the UI, such as borders, buttons, and so on, as shared resources, in a large map set calledreusing a atlasOther non-reusable UI is divided by function module, each module uses one orFeature AtlasFor some UI, if you use theFeature AtlasAndreusing a atlas, but itsFeature AtlasThe rest of the "vacancy" is more, you can consider the use of thereusing a atlasThe elements are carried out separately, intoFeature AtlasSo that the UI relies only on theFeature Atlas。 That is, through a certain amount of redundancy, to achieve performance improvement. UI elements that have the same textures and textures can be batch, and the batch UI can stack up and down without impacting performance, but if the UI elements of batch are not stacked together, the drawcall overhead is increased. To pay attention to the cascading relationship between UI elements, it is recommended to use the "T" tool to see its rectangle size, because some of the pictures are transparent, but stacked on top of the other UI, and then not batch, there will be no reason to many drawcall; the most visible UI is the image and text component, When text is stacked on top of the image (such as a button), and then a picture is stacked on the text, there will be at least 2 more drawcall, consider printing the font directly on the image below, and in some cases consider artificially increasing the hierarchy to reduce drawcall, For example, a text hierarchy of 0, another batch of text stacked on a picture A, Level 1, then 2 text because the hierarchy will be arranged 2 drawcall, but if a transparent picture in the first text (with picture a can be batch), The two-text hierarchy is the same, drawcall can be reduced by one. Should try to avoid using mask, in fact, the mask function can be implemented in some cases, such as the design of a border, so that the border is stacked on the top, the bottom of the UI is moved, it will be obscured by this frame, if you want to use mask, you need to evaluate the performance of the mask will be reduced and minimize it. For example, if the UI inside the mask is dynamically generated (like a list component), you need to be aware of the overlap between the generated UI; take a good lookUnity GUI-level merge rules and batch generation rulesThis section.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.