Skip to content

Conversation

@mihe
Copy link
Contributor

@mihe mihe commented Nov 28, 2025

Fixes #113058.

The current implementation of Node*D::reparent, when called with keep_global_transform at its default of true, does the following:

  1. Cache the previous global transform.
  2. Remove the node from its current parent, thus emitting NOTIFICATION_EXIT_WORLD.
  3. Add the node to its new parent, thus emitting NOTIFICATION_ENTER_WORLD, but with a potentially new (incorrect) global transform, since the local transform is what's actually preserved in the transition.
  4. Set the previous global transform again (and thus a new local transform).

This creates problems for nodes where the value of the global transform is important at the time of NOTIFICATION_ENTER_WORLD, like for example kinematic physics bodies, such as CharacterBody3D1.

This PR "fixes" that by changing Node*D::reparent to instead set the new local transform before we do remove_child/add_child, so that the node already has the correct global transform by the time add_child is called.

This of course means that now we won't have the correct local/global transform when NOTIFICATION_EXIT_WORLD/NOTIFICATION_EXIT_TREE is emitted instead, so arguably just trades one bug for another, but I figured this might prompt some discussion for better a solution.

The proper solution to this (at least in my mind) would be to instead restore the previous global transform inbetween these two lines, as opposed to before/after them:

godot/scene/main/node.cpp

Lines 2077 to 2078 in 7ed0b61

data.parent->remove_child(this);
p_parent->add_child(this);

... but I struggle to come up with a clean way of doing so.

Footnotes

  1. This seems to have "worked" with Godot Physics due to what to me looks like a bug in that implementation, but which is not present in the Jolt Physics implementation.

@fire
Copy link
Member

fire commented Nov 28, 2025

See #74659 for an alternative solution for get_global_transform()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Jolt Physics - When Reparenting a CharacterBody3D, Area3D nodes that are elsewhere get triggered

2 participants