Search Unity

Unity UI Performance tips - Sharing my findings

Discussion in 'UGUI & TextMesh Pro' started by vexe, Apr 4, 2018.

  1. vexe

    vexe

    Joined:
    May 18, 2013
    Posts:
    644
    Greetings,

    so after a day of doing research on Unity's UI, it's not so obvious pitfalls, quircks, dos and donts etc. I've compiled a list taken from misc Unity optimization tip articles and videos, mostly related to UI. We just starting a brand new smaller scale project and I thought it would be a good chance, fairly risk free to try Unity UI for a bit, as we've made all our previous games with NGUI and while it got the job done, we had a lot of beef with it. I thought Unity's UI would easily be faster since it's better integrated to Unity with a team of optimizers behind it, but it didn't turn out to be that simple. A lot of the decisions in the components and systems of the UI (e.g Layouts) are built in a way that it's very easy to shoot yourself in the foot with it. Hidden performance costs riddled across the codebase (see linked video). Documentation (except the optimization 'articles') was pretty lacking, mostly telling what the difference between system A and B is but not giving hints/advice on when to use when or what the cost of using a system over another in certain circumstances etc (e.g. Canvas Rendering modes). A lot of the optimization tips tells you to *not* do what the tutorials tell you to do (e.g. avoid Layouts etc).

    This stuff goes beyond 'make your game correct first then fast later' cause you could quickly and easily build up bad habits and practices and end up later with a that's very hard if not impossible to optimize. Profile/optimize more frequently Imo to avoid falling into that at a later stage in your project. A lot of this is structural/archtectrual stuff that add up, not minor bit twiddling and tiny performance hacks that you could slap in whenver you want. So it doesn't hurt to start off correct from the beginning.

    Anyways here's my list, please feel free to correct me if I was wrong or inaccurate on of these points (It's also why I'm sharing it here).

    • Limit the usage of 'Best Fit' and 'Rich Text' in Text components
    • Don't use dyanmic, use bitmap/static fonts if possible
    • Limit the usage of Outline/Shadow components on Text game objects. Bake the effect in the bitmap font instead
    • Stick to 'simple' sprites if possible. Avoid large 'tiled' sprites
    • Flatten out the transform hierarchy. The more nesting the more transform calculations needed to position children correctly
    • Uncheck "Pixel Perfect" in the Canvas settings. Big performance hitter.
    • Screen Space Overlay UI is slightly faster than Screen Space Camera. In Overlay the UI is drawn on top of the screen immediately avoiding all the culling and sorting that Camera space has to go through. (The performance hit shouldn't be that critical, and Screen Space Camera is convenient though, so maybe go with Camera and see if it causes you issues down the line)
    • Avoid stacking UI images/text on top of each other to best of your ability. This causes more overdraw and will slow things down
    • Subdivide your UI to multiple canvases based on what's static vs dynamically moving. Changing the position/rotation/scale/sprite/text of a UI element in a canvas causes a rebuild of the canvas' mesh for all its children. So having a single Canvas for the entire UI of your game is not a great idea. Divide it into logical groups that update/change together. e.g. Maybe each menu/screen/subscreen/popup has its own Canvas, maybe the hud top has a canvas vs the hud's bottom, etc.
    • General tip: Avoid Camera.main calls as it does Object.FindObjectWithTag every time it's accessed! Have a direct reference to the camera you're using instead.
    • Prefer enabling/disabling the canvas itself instead of the entire gameobject. Avoiding OnEnable/OnDisable callbacks on the entire hierarchy which could be expensive.
    • Avoid LayoutGroups. Roll out your own (see linked video for more details)
    • Updated pooled objects properties first before enabling it when borrowing an object from the pool. This avoids unnecessary dirtying of the object's hierarchy
    • With ScrollRects with many items, attach a Canvas (with no Pixel Perfect) to the scroll rect so that scrolling the items won't dirty out the elements in the outer canvases
    • Pool the items in the view. enable/disable elements as they get in/out of view
    • Clamp the velocity of the scrollview so that you don't end up with very small deltas making very small changes to your elements without it being apprently changing on screen
    • Turn off Raycast Target for static or non-interactive elements. This reduces the number of UI objects the collision/click/input raycast checker has to go through to determine what UI elements should receive events
    • Take out GraphicsRaycaster components from Canvases that don't require input events
    • Pack your sprites together to reduce drawcalls. Use Texture Packer or Unity's atlas/packer systems
    // Questions/Uncertain:
    • Does moving the Canvas itself trigger a rebuild/makes it dirty, or does that only apply when moving one of its child elements? From what I've read so far it seems that it doesn't, only when you change the Canvas's children.
    • Still not a 100% which is faster/better, moving elements by their local/position or anchoredPosition?

    // Links:
    - https://unity3d.com/how-to/unity-ui-optimization-tips
    - https://unity3d.com/learn/tutorials/topics/best-practices/guide-optimizing-unity-ui
    - 24:00


    Thanks
     
    Last edited: Apr 4, 2018
  2. Xelnath

    Xelnath

    Joined:
    Jan 31, 2015
    Posts:
    402
    Very helpful tips, thank you!
     
  3. Xelnath

    Xelnath

    Joined:
    Jan 31, 2015
    Posts:
    402
    Is using the unity UI better than direct drawing texture to screen?
     
  4. vexe

    vexe

    Joined:
    May 18, 2013
    Posts:
    644
    You mean rendering each texture/image individually without batching them into a single draw call? I'd imagine that's more expensive, more draw calls.
     
    Last edited: Apr 4, 2018
  5. sledgeman

    sledgeman

    Joined:
    Jun 23, 2014
    Posts:
    389
    Thx for this overview of tips !!!
     
  6. SM_AF

    SM_AF

    Joined:
    Aug 1, 2017
    Posts:
    23
    Thanks for the tips.
    One question: if you move an object, but to the same position (for example some off-screen indicator of an object that is not currently moving and player camera is not moving/rotating as well) - is the canvas going to get dirty or not?
     
  7. kencoderhk

    kencoderhk

    Joined:
    Dec 11, 2018
    Posts:
    9
    Thanks for Sharing:

    Re: "Subdivide your UI to multiple canvases based on what's static vs dynamically moving. Changing the position/rotation/scale/sprite/text of a UI element in a canvas causes a rebuild of the canvas' mesh for all its children. So having a single Canvas for the entire UI of your game is not a great idea. Divide it into logical groups that update/change together. e.g. Maybe each menu/screen/subscreen/popup has its own Canvas, maybe the hud top has a canvas vs the hud's bottom, et"

    I knew this recently too, but doubt how to use. Because using different canvas will break the graphic batch (more batch needed).

    So is it better to keep dynamic & static canvases first and breakdown to more if the performance isn't good?
     
  8. setting_up

    setting_up

    Joined:
    Dec 28, 2018
    Posts:
    1
    one of the best solution in my opinion is that create images with those static texts(that won't changed at all).in this way unity won't need to relayout graphics for this particular text.
    Example:
    if you have a button with a text with it , you can create this button at one single image and remove text from unity.
     
    rahulk1991 likes this.
  9. Chris_Payne_QS

    Chris_Payne_QS

    Joined:
    Jul 16, 2016
    Posts:
    84
    That's fine until you need to localise it. Then you've got the different problem of creating a new set of UI graphics per language.
     
    rahulk1991 likes this.
  10. Yamin-Nather

    Yamin-Nather

    Joined:
    Dec 31, 2014
    Posts:
    5
    Changing the text value in the text component doesn't dirty the canvas. But other properties like color and stuff still triggers a repaint. Not sure why though.
    But its still better to make a static text into an image cuz text components are not batched with the images.
     
  11. Layarion

    Layarion

    Joined:
    Jun 5, 2020
    Posts:
    10
    what does "dirty" mean?
     
  12. exiguous

    exiguous

    Joined:
    Nov 21, 2010
    Posts:
    1,749
    Dirty means nasty. Just kidding. In this context dirty means that (parts of) the UI has changed and needs to be rebuild. But its also used for objects in editor and scenes. So it generally means that something has changed and some further action is neccessary. It's kind of a flag which can be queried. For example when you changed the scene in the editor it is flagged dirty and when you attempt to close the editor it checks the scene dirty flag. If it is dirty the Editor asks you wether you want to save the changes or not. When you save the scene manually before closing, the dirty flag is removed and the Editor can close directly.
     
    RentedMouse likes this.