Reparenting a CharacterBody3D with keepGlobalTransform set to true still triggers an area3D placed in world origin, as if for a frame the characterbody moved to world origin and triggered the area3D, then moved back to its actual global position. Even if the CharacterBody3D is nowhere near the area 3D.
Any way to work around this bug?
#Reparenting CharacterBody3D elsewhere triggers area 3D on world origin
30 messages · Page 1 of 1 (latest)
hm, does it happen no matter the position?
it does sound like an oversight that should be reported.
Yes, the characterbody can be anywhere
I'll try to test in a minimal project to make sure it's not something else in my project. If I can reproduce it I'll report it.
An I guess I'll just move all my levels up so there's no area 3D at world origin to avoid this happening
Looking inside the Source Code (god bless open source):
void Node3D::reparent(Node *p_parent, bool p_keep_global_transform) {
ERR_THREAD_GUARD;
if (p_keep_global_transform) {
Transform3D temp = get_global_transform();
Node::reparent(p_parent, p_keep_global_transform);
set_global_transform(temp);
} else {
Node::reparent(p_parent, p_keep_global_transform);
}
}
it seems to "keep" the global transform by just saving it and then applying it afterwards, which i guess could can cause issues if not done correctly.
you could try a "custom" reparent-function (only applied to position instead of all transform for simplicity):
func reparent(node : Node3D, new_parent : Node3D) -> void:
var glo_pos : Vector3 = node.global_position
node.get_parent().remove_child(node)
node.position = new_parent.to_local(glo_pos)
new_parent.add_child(node)
this one changes the position while its outside the tree, so it should always use the correct one.
also, i think that function might have to be called using call_deferred(), and maybe that could also help with the original issue?
I'm using C#. Do you know how to call deferred in C#?
oh right, my bad almost forgot 😅 . using that custom function might also be tricky, although finding the equivalent should be much easier.
Here, that should be the best way of using call deferred.
https://docs.godotengine.org/en/stable/classes/class_callable.html#class-callable-method-call-deferred
there is also a function inside the object class, but that one uses strings to identify the function.
Thank you
do tell if just using call deferred fixes the issue, i remember it being pretty important when it comes to properly reparenting a node.
I tried calling deferred but that didnt solve it
i see, next i would try implementing the function i suggested, although you would of course have to change the syntax for C#.
oh, one more thing, does it also trigger the area when disabling keep global transform?
I'll test that
I'm trying to test on a new minimal project now
I tried to reproduce it in a new project and... it doesn't happen. So it's something I did in my project
Now I'm stumped. I have no idea what I have done to create this issue 😭
Oooh, wait, I'm using jolt physics in my project. I changed the minimal project to jolt physics and it does happen too!
So it's a jolt physics bug
i see, wouldn't be the first time there are pretty drastic differences in how they act.
although that one does sound potentially more significant than the one where the Characterbody does only report things like is_on_wall() by actually moving into it.
so still report-worthy, but now you were able to narrow it down quite a bit.
GitHub
Tested versions Reproducible in 4.5.1 (didn't test other versions). System information Windows 10 - Godot v4.5.1.stable - Vulkan (Forward+) - NVIDIA RXT 3060 ti Issue description This bug appar...
Now I tried changing the physics engine back to GodotPhyisics3D and the issue doesn't happen, but the performance hit is PAINFUL... I guess I'll keep using Jolt and just try to work around the issue while the bug isn't fixed.
I was able to do it a different way, without reparenting. What I was trying to do was to make a character grab and hang on to the edge of platforms, including moving platforms. I was reparenting the player to the platform so it would stay attached if the platform was moving. Now I changed the logic and simply made the player follow the movement of the platform without actually reparenting anything (which I now think is the best approach anyways)
yeah, having to reparent for that doesn't sound like the best way.
I learned my lesson 😆
althoguh there definitely are good reasons for reparenting, and the issue could also be significant there. Although maybe it's more relevant for 2d than for 3d, as tree structure matters when it comes to draw order.