0
\$\begingroup\$

I have the following Unity Visual Script triggered on a Start:

enter image description here

It looks at a child GameObject that uses Rect Transform and has a Text Mesh Pro component, and attempts to calculate the width of the text using the Get Size Delta of the Rect Transform.

Here's the odd thing: the attached script always returns a width of 0. I think that's because the script is triggered on Start, and by then maybe the anchors haven't been set yet. That's my theory at least, because if I run this exact same code on another event besides Start... the Size Delta returns appropriate data, and it always calculates the width properly.

I'm pretty sure I could set some sort of time-based delay, and I would get the proper results... but I'd like to understand the issue better and not just kludge it.

When exactly do anchor points get set? Is there a way I could call this code in such a way that it consistently generates a width that's non-zero?

\$\endgroup\$
6
  • 1
    \$\begingroup\$ I don't know what this script graph does and why. But most cases I saw where people tried to mess with RectTransform's were cases which could have been solved far easier and cleaner by properly utilizing the auto layouting system. \$\endgroup\$
    – Philipp
    Oct 11, 2022 at 10:51
  • \$\begingroup\$ @Philipp Upon a Start, the code is just looking at a Rect Transform, and pulling the Size Delta from it and looking at the X value of the Size Delta. \$\endgroup\$
    – kanamekun
    Oct 11, 2022 at 11:40
  • \$\begingroup\$ Yes, but why and for what purpose? \$\endgroup\$
    – Philipp
    Oct 11, 2022 at 11:50
  • \$\begingroup\$ It is getting the width of the GameObject, because each GameObject can nest with other GameObjects... and so their local position relative to the parent GameObject is equal the width of the parent GameObject. \$\endgroup\$
    – kanamekun
    Oct 11, 2022 at 12:02
  • \$\begingroup\$ I am not sure if I understand fully what you mean with "can nest with other GameObjects", but it sounds like something you could do with a horizontal layout group. \$\endgroup\$
    – Philipp
    Oct 11, 2022 at 12:09

2 Answers 2

2
\$\begingroup\$

From the documentation for Canvas.ForceUpdateCanvases():

Force all canvases to update their content.

A canvas performs its layout and content generation calculations at the end of a frame, just before rendering, in order to ensure that it's based on all the latest changes that may have happened during that frame. This means that in the Start callback and the first Update callback, the layout and content under the canvas may not be up-to-date.

Code that relies on up-to-date layout or content can call this method to ensure it before executing code that relies on it.

So you can call this method to update the anchors on demand. Just note that calling it repeatedly in a frame - such as in the Start() method for many UI elements that were all spawned that frame - might be expensive due to redundant computation. You may want to orchestrate your code so the method is called just once from a central manager script, which then calls a custom layout update method on each spawned item to respond to the new info.

Or you might want to implement your custom layout logic as its own auto layout component, by implementing the ILayoutElement, ILayoutGroup, or ILayoutSelfController interfaces as needed. Then your custom layout logic will get called within the flow of the canvas's main layout update, in correct dependency order. This saves you from kludging around the layout updates in Start/Update/coroutine functions.

\$\endgroup\$
7
  • \$\begingroup\$ Interesting, thank you so much! I'm not using Canvas on these GameObjects though; would Canvas.ForceUpdateCanvases still work? \$\endgroup\$
    – kanamekun
    Oct 11, 2022 at 20:39
  • 1
    \$\begingroup\$ RectTransforms only do their work if they're under a Canvas, somewhere in the parenting hierarchy. The canvas does not need to be directly on the element in question, it just represents the root/top-level container of a UI layout. \$\endgroup\$
    – DMGregory
    Oct 11, 2022 at 20:41
  • \$\begingroup\$ I used the Height and Width of the Rect Transform a lot, especially together with the Content Size Fitter. The Anchor and Pivot features also helped me align GameObjects nested below it. I didn't use Canvas though; is that considered a bad practice? \$\endgroup\$
    – kanamekun
    Oct 13, 2022 at 0:58
  • \$\begingroup\$ You don't have a canvas component anywhere in your scene, not even as the great-great-great grandparent of this RectTransform? RectTransforms that are just free-floating, without being inside a canvas, shouldn't get any of their auto-layout features used, since it's the canvas that's responsible for invoking those and telling them the size of the space they need to fit in. \$\endgroup\$
    – DMGregory
    Oct 13, 2022 at 1:08
  • \$\begingroup\$ Yah I don't have any Canvas component anywhere in the scene. My parent is the main GameObject, and then under it is a nested GameObject with Text Mesh Pro component (this GO uses Rect Transform and Content Size Fitter). And under that are 3 GameObjects that all use Rect Transform and are positioned relative to the nested GO that uses Text Mesh Pro. The positioning of these 3 GameObjects relies on the Anchor Points and Pivot of the nested GO which uses Text Mesh Pro... \$\endgroup\$
    – kanamekun
    Oct 13, 2022 at 2:40
0
\$\begingroup\$

I was able to get this working by changing two things:

  1. I made it into a coroutine
  2. Just before the width is calculated, I added code to make it Wait For Next Frame.

Those two tweaks fixed it! I guess Unity needs an extra frame to set the anchor points. Still not sure why anchors take time to be set, but this should fix the problem for now.

\$\endgroup\$
1
  • 1
    \$\begingroup\$ Update: using Canvas.ForceUpdateCanvases(): instead of Wait For Next Frame fixed the issue as well! I went with that option, as it directly addressed the issue instead of being a bit of a kludge. \$\endgroup\$
    – kanamekun
    Oct 13, 2022 at 7:34

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .