How can I make an instant grab system for Rigidbodies?

Godot Version

4.2.2

Question

The title should be self explanatory, but to explain it a bit more:
I want a grab system which sort of “locks” the grabbed rigidbody to the camera, but still allows the rigidbody to avoid walls.
I have managed to make 2 examples which showcase the wanted effect in 2 parts, first part showing how I want the object to look when picked up, second how I want the object to react to collisions:
Example 1:
https://www.youtube.com/watch?v=KqE4CNMTc6s
Example 2:
https://youtu.be/96FO8wpWtIA

So in short, I want to achieve the instant/no jitter grabbing like in the first example which was achieved by updating the grabber (a Node3D that the Rigidbody is parented to) to the camera’s transform in _process, while also reacting to collisions like in the second example which was achieved by updating the grabber in _physics_process, which unfortunately gave the jittery effect because of the difference in physics fps and render fps

Have you tried example 2 with a higher physics tick? If that solves the jitter then you may have to wait for 4.4 to implement physics interpolation, or use a higher physics tick.

Yeah, I did try that and it has fixed the issue, but I didn’t use that solution for obvious reasons.
So I assume there isn’t a way to get the best of both worlds, where the Rigidbody stays perfectly locked to the camera while also reacting to physics?

Using Engine.get_physics_interpolation_fraction() you can implement a (maybe) frame-behind interpolation as I understand it. Since you are picking up one object this might be easier than my own tests on a whole bag of goodies.

You would have to top-level the visuals or un-child them from the rigidbody, then use the rigidbody transform

func _ready():
  prevTransform = Transform2D(trackTarget.transform)

func _process(delta):
  transform.origin = prevTransform.interpolate_with(trackTarget.transform, Engine.get_physics_interpolation_fraction()).origin
  prevTransform = Transform2D(trackTarget.transform)

— from reddit

You could try updating the object’s position after everything else is done updating. This is the goto fix for camera jitter in unityland. Update things that depend on others in lateupdate.

There are two ways you can do that in Godot.
One is change the node’s process priority. (to -1)
(set_process_priority docs)

And the other is to use a call_deferred() function to update the position. The deferred function will be executed after everything is done processing.

But wouldn’t updating the position after everything else has updated render collisions useless?

I had previously tried it as a “2nd best” option, but the fact that the transform was still updated in _process, it still made the collisions not work.

Well it shouldn’t update the collisions, that script is only on the visual elements targeting an invisible rigidbody.

It might be able to phase-through edges and corners a little bit, but not breaking collision like in the first example.

1 Like

Ah right, I missed that part.
But with the way I have my grab system set up, I’m not sure how I can approach this solution.
Currently, once an object is grabbed I set it’s parent as the grabber and then give it a velocity that would center it back to a point in case it gets uncentered because of collisions and the grabber is the one that’s being updated, not the rigidbody itself.

1 Like

You would need a way to note the visual element of each grabble object. I think setting top_level = true would allow you to manipulate it through that script without having to worry about parent/child trees. Since Node3D has top_level you can stuff all the visuals as a child of a basic Node3D, maybe named “Visuals”, then child that to the object’s rigidbody.

Sounds like you would have a chain of updating nodes through scripts from grabber to rigidbody to visual.

1 Like

Hm, alright. I’ll look into implementing this solution as the current fix, until a way to achieve 100% of my wanted look is found.

Alright, after a moment I managed to implementing something which really helped with the jitter, still a bit sad there isn’t a way to make the grab system I wanted : p