godot icon indicating copy to clipboard operation
godot copied to clipboard

In the _ready() function of the parent node, calling the location information of the child node under the ui container gets the wrong result

Open chamer-vati opened this issue 2 years ago • 11 comments

Godot version

4.0Beta14

System information

Windows10,Vulkan

Issue description

In the _ready() function of the parent node, calling the location of the sub node in the ui container gets an error result. For example, child nodes (such as labels) after Custom Constans is set in MarginContainer. In this case, getting the global_position of the Label in their parent _ready() function only gives the Global Position of the MarginContainer

Steps to reproduce

Enter the Test project file and run it directly.

Minimal reproduction project

Test.zip

chamer-vati avatar Jan 25 '23 10:01 chamer-vati

Some functions do not work in _ready, need to be used after a frame (yield)

Zireael07 avatar Jan 25 '23 11:01 Zireael07

Since _ready() is called from bottom up (children first) usually you can rely on children being ready. However, since ui needs the whole thing to be ready since parents affect childrens' positioning, you need to wait until next frame, as Zireael noted. At least that's what I think is happening.

aXu-AP avatar Jan 25 '23 11:01 aXu-AP

由于是自下而上(孩子优先)调用的,通常您可以依靠孩子做好准备。但是,由于 ui 需要准备好整个事情,因为父母会影响孩子的定位,因此您需要等到下一帧,正如 Zireael 指出的那样。至少我认为这是正在发生的事情。_ready()

Thanks, since this issue did not occur in the Godot3.5.1stable and early Beta versions, this confused me a bit.

chamer-vati avatar Jan 25 '23 14:01 chamer-vati

It seems to me that we are missing a signal or a notification for when the sorting of children is done. So there is no obvious hook to reliably track when container updates child positions. I guess you could use child's own item_rect_changed signal.

YuriSizov avatar Feb 14 '23 14:02 YuriSizov

Godot v4.2.1.stable.official [b09f793f5]

I encountered this one as well, and for my UI heavy game this is not just QoL but that requires a workaround compared to the 3.X logic, of having the correct global_position etc. available on ready.

I have built the logic in the scripts with the assumption/knowledge that onready the positions in the UI were already the predefined ones. this can also be "fixed" by having a "call_deferred" for the functions you want to execute in the _ready that are dependant on the initial position of the Control node.

Here a reproduction project:

ready position testing.zip

The Label is put at the bottom of the screen by the VboxContainer with Alignment "End". In the editor it shows the correct position of the Label, on _ready it prints an incorrect one (in this case (0,0)) and on _process it has the correct position.

Reneator avatar Dec 26 '23 17:12 Reneator

I would like to advocate for this to be changed from an enhancement to a bug, as this is breaking a lot of code in my project and this behaviour in godot 4 is not intuitive imo.

My need for this arises from me wanting to remember the initial position of a node, which i then would tween around/towards/from that initial position afterwards.

Reneator avatar Dec 26 '23 17:12 Reneator

@YuriSizov I don't believe there is a hook/signal/notification that would be able to accommodate this, but feel free to correct me. I imagine this is highly desired for most users for the common use case of not wanting to show the UI until everything is in its right place, same as you wouldn't want the curtain to come up on a theater cast as they're putting their costumes on and running across the stage. Unfortunately, though, I'm not sure there can be a built in signal or notification that could know when a container's children are done sorting, since it can be triggered to resort multiple times based on not only their children but their parents and siblings. I think maybe if anything it would be helpful to push for documentation to say for scripting your outermost container, wait a frame and have it pass down that it's safe to calculate or show stuff, but again, if they're gonna use those calculations to adjust the child even more, it'd cause another resort, meaning you'd need to wait another frame, etc. It's just kinda hard to have a notification based on what the user considers "done".

markdibarry avatar Dec 29 '23 14:12 markdibarry

This is not a limitation or designed feature in Godot. It is a serious bug, which was not reproducible in 3.x. Even if you want to document as a limitation, you cannot, as you do not know when it produces correct result and when not.

It is safe to assume that the core functionality of Godot is broken. This bug redefines the usability of _ready() function

tokengamedev avatar Feb 08 '24 14:02 tokengamedev

What's your suggestion for "solving" this? It's a limitation, not a bug, it's simply not possible to know this when _ready as other nodes are not ready, and might update some of their sizing on _ready, the solution is instead to provide some update point

Relying on _ready itself doesn't seem good to me to begin with, it's not guaranteed to be useable anyway because of other factors IMO, the shaping is done deferred for various reasons, including performance, but also because _ready just means this node is ready, not its later siblings, or it's parent, or siblings of its parent, etc.

The data in _ready isn't guaranteed to be valid and can change later, so the best approach is to not rely on it but listen to changes as suggested here

But I'm also unsure why you need this information? Containers are intended to handle sizing and knowing sizes isn't necessarily something usually needed, so this feels like an unusual problem

AThousandShips avatar Feb 08 '24 14:02 AThousandShips

It's a limitation, not a bug, it's simply not possible to know this when _ready as other nodes are not ready, and might update some of their sizing on _ready

This bug is not related to resizing done inside the _ready code. It is a different problem altogether. It is just loading the scene from the scene file. If resizing done inside the _ready or anywhere else, it is users' problem and not engine's.

Relying on _ready itself doesn't seem good to me to begin with, it's not guaranteed to be useable anyway because of other factors IMO, the shaping is done deferred for various reasons, including performance, but also because _ready just means this node is ready, not its later siblings, or it's parent, or siblings of its parent, etc. The data in _ready isn't guaranteed to be valid and can change later, so the best approach is to not rely on it but listen to changes as suggested here

so how and where do we know the size and position of child controls at the time of launch of the scene.

But I'm also unsure why you need this information? Containers are intended to handle sizing and knowing sizes isn't necessarily something usually needed, so this feels like an unusual problem

You are right, containers should handle the sizing, no body argues that. It is not an unusual problem. It is for animations, and the most important of them all why we need is pivot_offset It does not take from 0- 1, rather takes the local position inside the control

Moreover, thanks to you I got the workaround to the problem i.e., use objects inside Control for animation rather than objects inside containers. It will add one more layer, but hope it works. In 3.x it was a big mess

tokengamedev avatar Feb 08 '24 17:02 tokengamedev

This limitation is due to how the sorting is deferred, but it is related to sizing changes and avoiding spurious resorting when updating things, but in the end the node isn't ready until the full tree is and it'd be pointless to sort the nodes constantly

so how and where do we know the size and position of child controls at the time of launch of the scene.

You don't, it'd be unreliable information at best anyway, and treating a node's position as remotely ready until it's siblings and relatives are is pointless and misleading

The solution here is to have a signal and respond to it

_ready doesn't mean everything is ready, there's plenty of things that won't be available until the next frame or the next physics frame due to registering and updating

AThousandShips avatar Feb 08 '24 17:02 AThousandShips