I’ve been putting together a bunch of UI windows and elements the last few weeks and been pretty content with the direct relation between the limits of what I know and what I can do. One thing, however, has been blocking me over and over and I can’t seem to find a clean explanation of the pattern I’m missing. It prevents me from signing off on my scripts and introduces a lot of mess as I desperately spin around in circles trying to fix it.
Issue
Opening and closing is an inherent action for UI, yet every time I set up my initial updates for a UI, I run into cases where visual updates are being skipped. Tabs will load their pages, but the Selectable on the tab itself won’t receive a styling unless I make redundant calls to refresh it. Modals will load, canvases will toggle, but they won’t resize unless I insert coroutines that delay the action for a few frames or toggle on and off manually. I have one script that needs to wait at least 3 frames before it will successfully draw the changes I sent to it and I have no clue where that number comes from.
In all of those cases, the code that’s skipped is identical to the code that ends up running successfully. It’s a timing issue as far as I can tell and as far as my team’s been able to suggest. It primarily affects when UI is loaded for the first time, and doesn’t so much affect refreshing done to an already open canvas. The Selectable state on my tabs will be marked correctly, but the visual state won’t match.
I assume I’m missing something critical about the order of operations for draw actions, and I’m also missing how to either avoid or adapt to it. I’m pretty sure this is a common pattern I just haven’t gotten into my head yet.
The number of frames I have to wait feels arbitrary. The updates which do or don’t get skipped feel arbitrary. I’m guessing blindly and sticking this pattern wherever I run into it in the hopes that it’ll work.
if (refreshCoroutine != null) { StopCoroutine(refreshCoroutine); }
refreshCoroutine = StartCoroutine(RefreshUI(1));
IEnumerator RefreshUI(int frameDelay = 3)
{
for (int i = 0; i < frameDelay; i++) { yield return null; }
UpdateThing();
}
I’ve tried switching between toggling a UI’s canvas or its canvas’s GameObject and the same problem occurs. I’ve tried running Canvas.ForceUpdateCanvases();
with no change. I’ve tried enabling, then updating, or reversing the pattern.
Any help would be appreciated as I’m in full guess mode right now which is not a smart way to code.