godot
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
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
Some functions do not work in _ready, need to be used after a frame (yield)
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.
由于是自下而上(孩子优先)调用的,通常您可以依靠孩子做好准备。但是,由于 ui 需要准备好整个事情,因为父母会影响孩子的定位,因此您需要等到下一帧,正如 Zireael 指出的那样。至少我认为这是正在发生的事情。
_ready()
Thanks, since this issue did not occur in the Godot3.5.1stable and early Beta versions, this confused me a bit.
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.
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:
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.
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.
@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".
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
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
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
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