Search Unity

Resolved uGUI Optimization

Discussion in 'UGUI & TextMesh Pro' started by Osteel, Aug 26, 2022.

  1. Osteel

    Osteel

    Joined:
    Jan 17, 2014
    Posts:
    59
    Hi, thanks for doing this! I have a few questions. I hope they're related enough to keep within a single thread.

    1. Is there any plan on optimizing uGUI or is the plan to move to UI Toolkit completely? Specifically things like layout groups, content size fitters and such that even Unity suggests not using because of how it rebuilds the canvas?

    2. On the topic of content size fitters, what is the correct way to nest them? There are many cases where UI needs to fit children elements (especially for scroll rects), but the children elements themselves also need to resize to fit their own content. However, this throws a warning in the editor?

    3. On the topic of canvases, I still get a little confused about nesting. Is it correct that a canvas rebuild won't cause parent canvases to rebuild, but children ones will? Or does a canvas complete isolate itself?

    4. How many canvases are too many? I know it's impossible to give a number, but should we be abusing them for complex UI such as long scroll rects with lists of things?

    5. I currently have this UI which is a bit sluggish on older devices. What would be a proper way to optimize this? Is turning on/off unseen ingredient blocks just the best thing to do? (That is, turning off the canvas of each block, since enabling GameObjects rebuilds the UI if I recall?)
    Thank you!
     
  2. phil-Unity

    phil-Unity

    Unity UI Lead Developer

    Joined:
    Nov 23, 2012
    Posts:
    1,226
    1. uGUI is getting bug fixes but the core engineering team is focused on UI Toolkit.

    2. There isn't a great way to nest them. If you have the system update twice or it should be ok in terms of getting to the correct result. The issue is the linear logic of the layout system not knowing it needs to ask for the size again.

    3. Correct a nested canvas having to rebuild in itself wont have the parent canvas rebuild. Now if the nested canvas moves the parent will have to rebuild due to the batching algorithm sorting things together that may appear above and below the nested canvas.

    4. I typically thing 1 canvas alone is too few, and 1 canvas for EVERY element is too many. find a middle ground :). If it makes sense in terms of something is always updating but its siblings doesnt' add a canvas, Long scroll rects i think would be valid.

    5. How are you layout out that scroll view? are they in any sort of vertical layout group?
     
    karl_jones likes this.
  3. Osteel

    Osteel

    Joined:
    Jan 17, 2014
    Posts:
    59
    Thanks for the responses!


    By updating twice, do you mean using something like ForceRebuildLayoutImmediate after each content size fitter is updated?


    This is a good point. Typically I put a canvas on each grouped element in a long scroll rect, but if they're just static themselves (aside from initializing them with their content), I suppose I might have been overkilling things and should just keep a single canvas on the root scroll rect.


    Here is a screenshot of the setup.

    • Each of these blocks are their own canvas with their own graphics raycaster because each has a single button to upgrade them.

    • They are a children of Content which has a Vertical Layout Group and Content Size Fitter. Both of these are disabled at runtime after the content has been populated (they're instantiated based on the save data)
     
  4. Trisibo

    Trisibo

    Joined:
    Nov 1, 2010
    Posts:
    245
    2. Personally, I tend to avoid content size fitters if possible, and mostly use layout groups (nested as needed) with some careful setup of layout elements. In the projects I'm currently working on, we used to have content size fitters on objects with parents that had layout groups, and it indeed caused issues (it would look correct at one point, but then break if something changed, like texts, etc.), but I've been redoing those setups with layout groups and layout elements, and after quite a bit of trial-and-error we have had no issues since then, they adapt to practically any content and any screen, and immediately (in one layout update).

    I know it depends on the situation, but is this a "proper" approach, is there a better one?
     
  5. phil-Unity

    phil-Unity

    Unity UI Lead Developer

    Joined:
    Nov 23, 2012
    Posts:
    1,226
    Yes something like that. After each content might be a bit extreme. End of frame might be enough just so it executes the layout again.


    Likely a little over kill with each canvas as then for each element it will have to go through the raycaster, it should be ok but maybe the cause of the issue.

    Glad to hear you are disabling the layout and size fitter components this is likely the single biggest thing for cost saving.

    In terms of masking on the content area is it still "Mask" or did you change it to RectMask2D?
     
  6. phil-Unity

    phil-Unity

    Unity UI Lead Developer

    Joined:
    Nov 23, 2012
    Posts:
    1,226
    Thats the power and downfall of uGUI. Its flexible enough that there really isn't 1 "proper" approach. My take is if its working for you not causing performance issues (really dont see why your way would cause performance issues) the its as valid as any other approach.
     
    Trisibo likes this.
  7. Osteel

    Osteel

    Joined:
    Jan 17, 2014
    Posts:
    59
    Deep down, I've always felt that this was the solution to nested fitters, but it's been hard to find the time to really sit down and figure it out. Hacking around it gets the job done in short deadlines. However, I think this is motivating me enough to master layout groups properly. :D


    Yeah, I'm definitely going to try to move it to a single canvas and see how that performs. Thanks for confirming that it may be a problem, it's always felt a little wrong to me but I've been sticking with it out of habit.


    Checking it and it's using the Mask component. I suppose we should be using RectMask2D based on your question. That should be a quick swap!
     
  8. phil-Unity

    phil-Unity

    Unity UI Lead Developer

    Joined:
    Nov 23, 2012
    Posts:
    1,226
    This should help on older devices as well. Mask uses the stencil buffer and has to do a bunch of material "magic" to ensure proper layering. Older devices dont always support the stencil buffer and some that do aren't quick.

    If you are fine with a rect mask vs having any rounded corners (Based on your image you will be fine) i'd use RectMask2D.
     
  9. Osteel

    Osteel

    Joined:
    Jan 17, 2014
    Posts:
    59
    Thank you for answering all these questions. Excited to read the other threads as well. :)
     
    phil-Unity likes this.