Camera stutters in a simple rotation?!

Here's is my method for rotating the camera which is called every LateUpdate():

void RotateCamera(float angle){
        nextRotateAngle = Mathf.Lerp(nextRotateAngle, angle, Time.smoothDeltaTime * 2f);
        this.transform.RotateAround(lookAtPos, Vector3.up, freeRotateSpeed * nextRotateAngle);
    }

Which, you may argue isn't lerping smoothly or what have you; so even when I change it to something as basic as this:

this.transform.RotateAround(lookAtPos, Vector3.up, 2);

Where 'lookAtPos' is the position of a stationary rigidbody (character) there is still some lag/stutter in the movement. The profiler isn't showing any unusual spikes during the stutter and the character is staying still at a velocity of zero (I can assure you this). The rotation is done in LateUpdate() and the movement in general is very smooth, even when the framerate is at a constant 60fps. The fixed timestep in the Time manager is set to (1/60) to match the framerate so... what on earth is causing this occasional stutter?

It happens about 5% of the time during the movement (so if I leave the camera spinning around the character like in the second code snippet, it will just stutter ever so slightly for no apparent reason) and I don't understand why.

Any ideas at all?

Moving the method to FixedUpdate() or Update() doesn't work. Character is on Interpolate (even if that's not relevant as the camera isn't changing position).

Edit: It seems as time goes on, the frequency of how often the stutter happens seems to increase...

Time.smoothedDeltaTime? I've never used it, always used Time.deltaTime without issue. What is this for?

In your basic example you should use Time.deltaTime because elapsed time between frames is not constant, which makes the movement jurky when the amount of movement is constant.

1 Like

SmoothDeltaTime has given me smoother results everywhere I've used it so, even when changing it to DeltaTime, it's still stuttering. Honestly I don't think the issue lies with the code; maybe a setting somewhere?

I don't know about Time.smoothedDeltaTime. So I have no idea if it is causing the problem or if it really helps to get smoother movement. Does someone knows exactly what it does? The documentation says nothing specific about it!

However, Update is for sure not called at fixed interval; the time between two Update varies. That's why we have Time.deltaTime, which gives the elapsed time since the last frame. And that's why we have FixedUpdate, which is called at fixed interval of time.

I'm not 100% sure of the difference myself but it has given me smoother results most of the time. I always test between the two but in this specific situation, the stutter must be affect by something else.

It's definitely not an update issue and I'm almost certain that the issue is to do with some time setting somewhere. I'll try and show a visual representation of the stutter.

So, imagine the '-' is a smooth movement, and the '|' is a jitter. Here's what I'm getting for a full 360 degree rotation around the object:

-----------------------------------------|-------||--------|----------|-------|-------------|-------------|----|------------
and then the next 360 rotation will be like:
-------------------------|--------|----|---------------|-----------------|------|-------------------|----|-------|----------

See how it's very inconsistent and that, for the most part, I get a very smooth movement?

Dude, rtfm:):
http://docs.unity3d.com/ScriptReference/MonoBehaviour.Update.html

Moving it to Update() and changing the deltaTime type doesn't make a difference (nor do all the different combinations).

Even if it's the only thing running and it's been tested in both LateUpdate() and Update() with delta and smoothdelta it still persists.

Do you mean there's still jerky movement with:

void Update()
{
    this.transform.RotateAround(lookAtPos, Vector3.up, 2.0f*Time.deltaTime);
}

Though, 2.0f* Time.deltaTime means the rotation speed is 2 degrees per second. That's very slow. Is that what you mean by stuttering?

Edit:
I'm wondering. Is the lookAtPos also moving?

Yes, EVEN with that plain and simple movement. When I add delta/smoothDeltaTime I would increase the float value so that's around the same speed; but yes, the jitter sill persists.

Even when I have it rotate around the point (0,0,0) and there's nothing affecting it's movement/rotation to the point where the entire script for the camera is just simply calling that rotate function, the jitter still persists.

The character, when still, is set to have a velocity of (0,0,0) with no gravity/forces affecting it so it's definitely not an issue with the camera's target object.

Weird... Could post your project, or a simpler one reproducing the problem. I'm really curious about what's going on.

That's the thing, my NDA doesn't permit me to share core information on the project so I'll have to make a little mock up and make a video of it. It probably is an issue with a setting in one of the project files but... I'll see what I can do.

Of course you don't have to send your company assets. Start from an empty project with the minimum that reproduces the problem.

Okay, here's a download link to a mock project with the same project settings, with the same jitter:
https://dl.dropboxusercontent.com/u/56814081/Test.zip

Thank you.

I tested the scene. I rotated the camera using an analogue joystick at different speed. The movement is smooth, I don't perceive any jerky movement.

Are you sure the problem is not specific on your computer? Do you have a program running in the background? Maybe you should check your performance monitor.

My computer is definitely capable of giving a smooth performance so it can't be that; besides, the FPS is at a steady 60 the whole time. Even when it's the only thing running it still jitters. More-so in the actual project that the test mock one.

Even on the lowest (fastest) quality setting it persists.

Alright. I could reproduce it by setting a constant rotation speed, and not using the analogue joystick. I observed some random slow down and speed up during the rotation.

However, using the following works as expected:

    void RotateCamera(float angle)
    {
        this.transform.RotateAround(lookAtPos.transform.position, Vector3.up, 20.0f*Time.deltaTime);
    }

I don't understand the usage of the Lerp here and the Time.smoothedDeltaTime. Do you have the possibility to discuss it with the author? Maybe you should consider another alternative.

1 Like

Looking at the profiler, I can notice the in the 'Physics' part the 'active rigidbodies' goes quite nuts when rotating... but I don't see how the two are related, and the only rigidbody is the character which is remaining still and is coded very efficiently.

The lerp function I added was to accel/decel the camera when moving it. The value changes very smoothly and when at the maximum value it doesn't fluctuate, yet the jitter persists.
I'll try your code now...
Edit: it still persists >_<

I am trying hard. But this usage of the Lerp function does not make any sens to me. I know exactly how the lerp function works it's basically:
p = (1-s) *p1 + s*p2, where s is between 0 and 1.

That's the definition of linear interpolation. If you plug in s = Time.deltaTime (or Time.smoothDeltaTime). What the hell should be expected?

Personally, when I'm in this situation. I would ask someone to explain/justify it to me. If there is no one, I would search online if that's a known technique. If I still find nothing, I'd toss it and rewrite it in a way it's clear to me.

Okay, the value passed through the parameter is the player input. That goes from 0 to 1 very quickly, so that lerp function just slows that down. Therefore, rather than the camera going from 'not moving at all' to 'moving at full speed' is smoothed out, and when the player lets go, the camera will slow down to a stop rather than instantly stop.
When value lerps from itself to a finish value, rather than a set start value to a finish value, it smooths that entire process out.

Regardless, even if you remove that and just use 'angle' instead of 'nextRotateAngle', the stutter still persists.

From this point on, lets just assume that the problem is not with the rotational code, but maybe in a setting somewhere. Or that physics oddity in the profiler.