Slerp and Rigidbody jagged movement

Ok so I have been searching for a fix for this and after a few hours of searching I figured I should probably ask.

For my FPS controller I am using a rigidbody for movement, for setting the position of the players gun I am using this script:

//this is all in function Update ()
holding.transform.rotation = Quaternion.Slerp (holding.transform.rotation, transform.rotation, Time.deltaTime / (holdingInfo.myWeight/100)); //holding rotation lag
holding.transform.position = Vector3.Slerp(holding.transform.position, transform.TransformPoint(0,holdingInfo.myCamDisY,holdingInfo.myCamDisX), Time.deltaTime / (holdingInfo.myWeight/150));

“holding” is the instance of the gun that the player is holding.

The rotation of the gun is very nice and smooth but for the position half of the script the gun is very jittery with movement. I figure its because the rigidbody’s position that its following is being updated in the fixedUpdate.

Can someone help me with this?

Hm… Is there any specific reason you’re using Vector3.Slerp as opposed to Vector3.Lerp? Slerp gives you a spherical interpolation - i.e it moves around to the specified point, rather than moving directly to it. Is that what you’re looking for?
I’m not sure it applies here since it’s not the rigidbody that’s having problems, but you might also try changing you rigidbody’s interpolation settings.

Thanks for the reply FlamingHairball, I had tried using “rigidbody.interpolation = RigidbodyInterpolation.Interpolate;” in the update function before, is that how you use it?

I don’t know why I was using slerp before :stuck_out_tongue:
I am using lerp now but its the same result.

Nope, you should be able to assign the rigidbody interpolation in the inspector - you only need to assign it once.
Does the gun have a rigidbody attached to it? Have you tried moving it in FixedUpdate rather than Update?

The gun has no rigidbody attached. I have tried assigning it in a fixed update but then the rotation was jagged, go figure :p.

I’m not sure if it’s causing the jitter you observe, but the way you’re using the time delta is wrong - you’re applying it like a linear correction when it’s actually exponential in your case.

The jitter may go away, though, if you move the code to LateUpdate.

Sadly it still doesn’t work, whats this about my delta time?

Thinking about this some more, your main problem is that FixedUpdate occurs independently of Update and LateUpdate. On any frame, Update and LateUpdate are called, followed by rendering. Before Update, however, FixedUpdate will get called zero or more times. After each FixedUpdate, the physics system advances too.

So if the render frame rate is high, Update may be called several times without an intervening FixedUpdate. If the render frame rate is low, FixedUpdate gets called many times before the next Update call. If you do your tracking in the Update or LateUpdate calls then you’re running out of step with the physics, and - crucially - the deltaTime in your Update is not the same as the amount of physics time which has passed. This is most likely what causes your jittering.

If you want to leave your code in Update, running it once per rendered frame with a variable timestep, then thats OK but you need to use the total FixedUpdate deltaTime for the current frame - i.e. count it up in FixedUpdate, use it in Update (for things that need to be in step with the physics), and zero it at the end of Update.

Otherwise, if you want your code to run with a fixed timestep but after the physics updates, you can put it in both FixedUpdate and Update, but only execute it if it’s not the first time in the frame. i.e. set a bool to “true” in Update or LateUpdate, and use that to skip the first execution of your post-physics-fixed-update code in the next frame. If the frame has no FixedUpdates then this will skip the only execution of your code for that frame, which is what you want too.

Example 1:

    private float totalFixedDeltaTime;

    void FixedUpdate()
    {
        totalFixedDeltaTime += Time.deltaTime;
    }

    void Update()
    {
        holding.transform.rotation = Quaternion.Slerp (holding.transform.rotation, transform.rotation, totalFixedDeltaTime / (holdingInfo.myWeight/100)); //holding rotation lag
        holding.transform.position = Vector3.Lerp(holding.transform.position, transform.TransformPoint(0,holdingInfo.myCamDisY,holdingInfo.myCamDisX), totalFixedDeltaTime / (holdingInfo.myWeight/150));
        totalFixedDeltaTime = 0;
    }

Example 2:

    bool firstPostPhysicsFixedUpdate;

    void PostPhysicsFixedUpdate()
    {
        if (firstPostPhysicsFixedUpdate)
        {
            firstPostPhysicsFixedUpdate = false;
            return;
        }
        holding.transform.rotation = Quaternion.Slerp (holding.transform.rotation, transform.rotation, Time.fixedDeltaTime / (holdingInfo.myWeight/100)); //holding rotation lag
        holding.transform.position = Vector3.Lerp(holding.transform.position, transform.TransformPoint(0,holdingInfo.myCamDisY,holdingInfo.myCamDisX), Time.fixedDeltaTime / (holdingInfo.myWeight/150));
    }

    void FixedUpdate()
    {
        PostPhysicsFixedUpdate();
        ...
    }

    void Update()
    {
        PostPhysicsFixedUpdate();
        firstPostPhysicsFixedUpdate = true;
        ...
    }

Thank you so much sir!

The first one didn’t work because of some camera rotation error but the second worked like a charm.