#Reparenting CharacterBody3D elsewhere triggers area 3D on world origin

30 messages · Page 1 of 1 (latest)

gaunt garden
#

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?

tepid sigil
#

it does sound like an oversight that should be reported.

gaunt garden
gaunt garden
tepid sigil
# gaunt garden I'll try to test in a minimal project to make sure it's not something else in my...

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?

gaunt garden
#

I'm using C#. Do you know how to call deferred in C#?

tepid sigil
#

there is also a function inside the object class, but that one uses strings to identify the function.

gaunt garden
#

Thank you

tepid sigil
#

do tell if just using call deferred fixes the issue, i remember it being pretty important when it comes to properly reparenting a node.

gaunt garden
tepid sigil
tepid sigil
gaunt garden
#

I'm trying to test on a new minimal project now

gaunt garden
#

Now I'm stumped. I have no idea what I have done to create this issue 😭

gaunt garden
tepid sigil
#

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.

gaunt garden
#

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.

gaunt garden
#

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)

tepid sigil
gaunt garden
#

I learned my lesson 😆

tepid sigil
#

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.