- Home /
Physics + first person camera = jitter?
I have spent a couple of hours trying to solve a seemingly trivial problem in an efficient way. Preface: I have many years of experience with Unity and am aware of the common pitfalls related to camera animation.
When having a fast moving object driven by physics, having a camera closely follow the object leads to intense jittering.
Everything happens in FixedUpdate and I have tried lerping the camera both in FixedUpdate and LateUpdate. Both interpolation and extrapolation have been tried. Fixing the camera to the object in question (either via parenting or simply setting the position in LateUpdate) eliminates the stuttering but is not acceptable as I want a certain inertia to the camera.
Which leads me to the question. Is the current physics implementation in Unity inherently jittery in a way that following a rigidbody too closely will reveal frame by frame inconsistencies? Even though FixedUpdate runs on a fixed timestep (which Update/LateUpdate does not) I had expected the interpolation methods to leave me with a consistent movement.
As it stands I can think of two workarounds: 1. Have a visual model follow the physics rig. It will be a tiny bit behind but this should not be visible. This way the camera will follow the stable (but "late") visual model instead. I am confident this would work, but it adds overhead to the programming and rigging. 2. Fix the camera to the physics object and implement my own stable routines to simulate the inertia.
I would be very thankful for some input on this. In particular from Unity devs or experienced members. Thanks in advance!
"Is the current physics implementation in Unity inherently jittery in a way that following a rigidbody too closely will reveal frame by frame inconsistencies?"
Not exactly. Assu$$anonymous$$g your code execution (and script execution) are in the most ideal possible order - with the camera moving last - the only room-for-error left is the actual velocity per frame. In other words, it's definitely possible that the source of the error is the followed object's speed, and not the camera's smooth-follow code. A great enough "step" in units is going to be a visible "jerk" to the eye, even at 30, 60 FPS.
The physics sim runs at 50 FPS by default. You could try increasing this, but don't go crazy. Its default is 50 for a decent reason, I'm sure.
In the past, I recall using a curve to control the camera's responsiveness and tracking speed based on the followed object's velocity to mitigate the jerky effect.
I am honestly not sure what is going on here. The problem is not as much related to physics as it is to one fast moving object smoothly following another. As far as I have seen, lerping after an object moving at high, uneven (but smooth) speed - ie. accellerating for example, does lead to perceived jitter. I have made sure the execution order is correct, the camera moves last in LateUpdate. The other object moves in a regular coroutine. Both reference deltatime through en exponential function (which is smoother than a simple deltatime multiple, which jitters worse).
$$anonymous$$y conclusion is that lerping and other similar methods are unsuitable for cameras closely tracking high speed objects. Or is there something fundamental I am somehow missing...?
same issue here, i have a child camera attached to a rigidbody (no smoothfollow), and everything goes crazy
Answer by Foxxis · Nov 01, 2014 at 03:47 PM
This seems to be a long standing "problem" in the Unity community, and it seems to never have been properly answered.
I am relatively certain the improper use of Lerp is the cause. x = Mathf.Lerp(x, targetvalue, Time.deltatime) is simply an sloppy approximation of an exponential function. It will work fine in situations where an exact interpolation is not critical. But in the case of a first person / chase camera following a quick moving object, it simply will not be exact enough.
There are several ways to properly solve the problem: 1. Use a physics driven camera as well and use forces/springs to make it behave as intended. 2. Implement a custom inertia model that uses available data to simulate inertia as needed. 3. Write a proper exponential function that is accurate for frame rate fluctuations.
I am going with option #2 as it suits our needs the best, and a quick test proves my answer. The jittering is gone and the camera behaviour is as intended. So in the end this had very little to do with Unity physics, and like I mentioned earlier I suspect this is the case for the majority of similar questions here and on the forums.
Answer by IkeHerman · Feb 28, 2015 at 03:02 PM
So, having just run this gauntlet myself, here is my thought which was alluded to in AlwaysSunny's Comment.
That basically the physics is running at a different frequency than the game. So here is my somewhat simple solution to the problem.
In your camera code, track the delta time that is actually accumulated on that physics update, and then use that delta time to calculate your camera velocities.
There is probably a more unity friendly way to do this, but in any case here is the list of what i did in my code and it completely removed the jitters.
Note: this only works for following physical objects, for something moved in Update(), you can just use deltaTime in your late update, but then again you probably aren't getting jitters.
float AccDeltaTime = 0.0f;
void FixedUpdate() {
AccDeltaTime += Time.fixedDeltaTime; // is there a way to query how physics update occurred?
}
void LateUpdate() {
Vector3.Lerp( current, target, rate * AccDeltaTime );
AccDeltaTime = 0.0f;
}
Answer by Zehs · May 24, 2019 at 11:38 AM
@IkeHerman In your code what would I set rate to? What value should I use?
Answer by lionelmarr · Aug 24, 2020 at 04:54 PM
I also had a jerky ride for a FPS on a lift. I tried what I could, including making the FPS a child of the lift. What seems to be happening was that the lift wouldn't move at the same speed as the physics. As the lift fell, the FPS was always catching up with the gravity and for much as I played with gravity speeds or interpolation, it never got acceptably smooth.
I found a reasonable workaround (after many hours).
My lift animation was triggered by the pushing of a button. I included in the code attached to the button a changing of the main camera to a secondary camera which was mounted in the lift (to change cameras: https://answers.unity.com/questions/1449917/switch-camera-to-an-additive-loaded-scene.html). This gave a perfectly smooth view.
Then I attached a simple mouse-look-around code to the camera (https://answers.unity.com/questions/29741/mouse-look-script.html- I used the second easier script by Andy P-123), so although it wouldn't move whilst in transit, you could still look around as if it was still the FPS.
I also deactivated the FPS whilst I was on the secondary camera, otherwise, there could be some discoordination and the FPS might be invisibly moved away.
Since the FPS was deactivated, I had to temporarily make the FPS a child of the lift, otherwise, it wouldn’t fall with gravity until it was reactivated at the end. To make it a child:
FPS.transform.parent = MyLiftObjectName.transform;
I put in a check to make sure that when the animation finishes, the FPS becomes active again, the camera resets to main and to stop the FPS being a child of the lift object.
void Update()
{
if (animator.GetCurrentAnimatorStateInfo(0).IsName("AnimationNameInInvertedCommas"))
{
FPS.SetActive(true); //public GameObject FPS; was declared at beginning of the script.
//Disable the second camera
m_CameraTwo.enabled = false;
//Enable the Main Camera
m_MainCamera.enabled = true;
//reset FPS so it is no longer a child of the lift
FPS.transform.parent = null;
}
}
I ended up using this solution to trigger the end of the journey as a mesh collider trigger didn't seem to work. I think this was because the FPS was inactive so it didn't make the trigger.
Your answer
Follow this Question
Related Questions
Inversing fixed delta time 1 Answer
Lerping orthographic camera size jitters 1 Answer
Camera jitter when using Lerp/Slerp 1 Answer
Jitter Camera Effect When Parented To Animated Object 2 Answers