Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reparenting frozen RigidBody3D breaks smoothing #58

Open
nanodeath opened this issue Jul 27, 2024 · 4 comments
Open

Reparenting frozen RigidBody3D breaks smoothing #58

nanodeath opened this issue Jul 27, 2024 · 4 comments

Comments

@nanodeath
Copy link

nanodeath commented Jul 27, 2024

Hi there. I have a CharacterBody3D character in my game that when they pick up a RigidBody3D, it static-freezes that object and reparents the object to the character, as well as adding the necessary collision-exclusion stuff. This mostly works, except for smoothing. The physics object itself will attach and move with the character as desired, which can be checked using Debug > Visible Collision Shapes, but the mesh stops moving with its parent object entirely.

Screencast.from.07-27-2024.08.15.02.AM.webm

In the above video, the left object is a normal cube, while the right object is using Smoothing. The expected behavior is that the mesh on the right will track the right collider, and generally look similar to the cube on the left. Both cubes reparent to the player after a 1 second delay.

SmoothingDesync.zip

And here's the repro project. Godot 4.2.2 + Smoothing 1.2.1. I've also verified it affects Godot 4.3-rc1 mono.

I don't have a workaround yet, but I was thinking of reparenting the mesh node depending on whether the item is being held. But also I don't really want to do that 😛

Thanks for looking!

@lawnjelly
Copy link
Owner

lawnjelly commented Jul 30, 2024

Sorry I took a while, I've been afk for a few days.

It looks like the problem is that on reparenting, you need to reset what the smoothing node is following. For convenience it automatically selects the parent node on _ready(), but you are changing the node path by reparenting after _ready().

The solution is to reset this nodepath by assigning the target again after reparenting:
$Smoothing.target = ".."

You may need to use a different script for the two different blocks in this example for it to work (as the control block doesn't have a smoothing node).

This could possibly be handled better by the addon, but not a great reason to change as core physics interpolation should be available soon even in 4.x (after 4.3).

@nanodeath
Copy link
Author

Is the problem the target node_path is resolved to an absolute path at runtime?

@lawnjelly
Copy link
Owner

Is the problem the target node_path is resolved to an absolute path at runtime?

Yes, it does a few things like this for safety, should the node be deleted, if I remember right (I wrote it years ago).

@nanodeath
Copy link
Author

The more I dive into this, the more interesting it gets 🙂 I think I see the problem.

The good news is _enter_tree is executing as expected when reparenting the object -- it's just the code isn't working the way we hope. And the culprit is...this line:

var parent = get_parent_node_3d()

During _ready, set_as_top_level(true) is called, which obviously sets the object as a top-level object:

set_as_top_level(true)

And we know _ready gets called after _enter_tree, because...in DOM terms, "enter tree" is called during the "capture" phase, while "ready" is called during the "bubbling" phase. That is, we call _FindTarget() (in _enter_tree) before calling set_as_top_level(true) (in _ready).

get_parent_node_3d is a little weird:

Returns the parent Node3D, or null if no parent exists, the parent is not of type Node3D, or top_level is true.
Note: Calling this method is not equivalent to get_parent() as Node3D, which does not take top_level into account.

(emphasis mine)


Basically, get_parent_node_3d will only ever work when the Smoothing scene is first created because it's called before top-level is enabled.

I think the solution is simply using get_parent. I'll test that out and sent our a PR for it if so.

nanodeath added a commit to nanodeath/smoothing-addon that referenced this issue Jul 31, 2024
Previously thsi was using get_parent_node_3d(), which returns null if
top_level=true, which it is. Thus this check is guaranteed to fail except
right when the Smoothing node is first initializing.

Closes lawnjelly#58.
nanodeath added a commit to nanodeath/smoothing-addon that referenced this issue Jul 31, 2024
Previously this was using get_parent_node_3d(), which returns null if
top_level=true, which it is. Thus this check is guaranteed to fail except
right when the Smoothing node is first initializing.

Closes lawnjelly#58.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants