Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Unity UI Canvas rebuilding flow? Logic error upon building canvas from code.

Discussion in 'UGUI & TextMesh Pro' started by Vince-Chimp, Jun 13, 2018.

  1. Vince-Chimp

    Vince-Chimp

    Joined:
    May 28, 2018
    Posts:
    42
    Hi everyone,

    I have a relatively simple canvas. It has 1 scrollview, with variable content all managed by a Vertical Layout Group.
    Above it are 4 tab buttons.

    Depending on which tab you tap, it opens that tab, and it goes like this:
    • Save current verticalNormalizedPosition for the open tab
    • pick the first X items in the vertical layout group, enable those, disable the rest. And refresh the content of said items.
    • Set the new tab index, and apply the previously stored verticalNormalizedPosition for this new tab to the scrollview.
    How what happens here, is that when all tabs have the same content length (E.G. 30 items) all goes well, and this functions.
    But as soon as my first tab has 28 items, and it switches to a tab with 30 items, verticalNormalizedPosition does not obey. I set it to 1f (all the way scrolled UP) and when reading it out, it gives me 0.9808f instead.

    Something tells me i have something in my above order wrong, or i have to force a redraw before setting that scrollview. The size of the Vertical Layout Group is probably not properly processed yet, and thus after it DOES process, the scroll position gets altered to reflect this change. (the changed distance * 0.5f it seems)

    How would i go about resolving this issue? I already attempted to use LayoutRebuilder.ForceRebuildLayoutImmediate, But this had no effect.

    Sincerely,
    Vince
     
  2. Hosnkobf

    Hosnkobf

    Joined:
    Aug 23, 2016
    Posts:
    1,096
    I also experienced the problem that the Scroll View is not set up within the first or second frame. Actually I wait two frames before I apply logic. That is a workaround which works for me but of course is not ideal.
    Maybe calling
    LayoutRebuilder.ForceRebuildLayoutImmediate
    twice would do the job (since one time doesn't seem to be enough). But I didn't test that yet (If it works: please let me know).
     
  3. Vince-Chimp

    Vince-Chimp

    Joined:
    May 28, 2018
    Posts:
    42
    In most cases, if you need to use ForceRebuildLayoutImmediate, you are using UI components wrong (i have seen it happen with nested scrollviews where objects would not be properly positioned at the end of a frame etc.)
    So i kind of got in the habit of finding out what else is wrong, because we all know that "wait a few moments, then do X" in a big project can cause a ton of problems because you expect some things to happen instantly.

    I just came back to this after finding something while brainstorming this with colleagues. I have now, after some more research, found that there is a monobehaviour event called: OnRectTransformDimensionsChange()
    This gets called when a (The transform of this script specifically) RectTransform changes size. In my case only when i enable/disable some of the child objects of the scrollView content.

    So to test, i checked the framecount, and it is identical to the frame i switch the tab in. So it doesn't have the issue your solution has. And if i set my verticalNormalizedPosition in that OnRectTransformDimensionsChange, it all works as expected.

    Obviously creating a script just to catch this event on the scrollView's content that then creates an event to which my UI script listens is not the coolest. But it seems to be reliable for what i want. Hit me up if anyone knows of a better way.
     
  4. Hosnkobf

    Hosnkobf

    Joined:
    Aug 23, 2016
    Posts:
    1,096
    Hmm... good to know that this is not a general ScrollRect bug.
    I guess the problem I am facing with the two frames is because of too many ContentSizeFitters in the hierarchy... Unfortunately I cannot get rid of them.

    However, OnRectTransformChange() is obviously also not called immediately, so the problem consists: you have to wait before setting the scroll position.
     
  5. Vince-Chimp

    Vince-Chimp

    Joined:
    May 28, 2018
    Posts:
    42
    I highly suggest you watch a few UI videos and strictly follow the buildup of a scrollview as unity provides it. These kinds of UI issues can be solved if properly layered and structured, i have seen and fixed them myself (given a week of racking my brain over what it was doing) You really need to get into the nitty gritty of the UI to understand what is going on and how to resolve the rendering/updating issues.

    For me, within the same frame is "immediate enough" for what i needed. But i do agree that there should be a better way to solve it still.
     
  6. Hosnkobf

    Hosnkobf

    Joined:
    Aug 23, 2016
    Posts:
    1,096
    Thanks for your suggestion. Actually, I think I have already a very deep knowledge of how the UI works. But you are probably right that I don't know enough yet about the rendering / layouting pipeline.
    My way of learning is to dig into the decompiled code of unity. That way I really see implementation details which are often not mentioned in tutorial videos.
     
  7. Vince-Chimp

    Vince-Chimp

    Joined:
    May 28, 2018
    Posts:
    42
    I agree. I am not saying you do not have a lot of UI knowledge.
    I wish i could help you with your problematic usecase. There is something i vaguely remember, which was warnings in the inspector with nested scrollviews and layout groups etc. that say something along the lines of: "hey you have nested X or Y, and that sometimes doesn't go right"

    It was those warnings that got our project buggered up, and resolving them with empty child objects and considering where all the layout stuff was, made the exact same UI possible, but without those warnings on the UI inspector elements. I hope that you are seeing something similar something in UI. That is all i can remember that could help you in your situation.

    Example: https://answers.unity.com/questions/1103253/warning-when-combining-content-size-fitter-and-ver.html

    Best of luck!
     
    Hosnkobf likes this.