Search Unity

Character in FixedUpdate() and Camera in LateUpdate() - Jitter Problem

Discussion in 'Scripting' started by Jakeiiii, Jan 19, 2016.

  1. Jakeiiii

    Jakeiiii

    Joined:
    Jul 7, 2014
    Posts:
    256
    I've modeled my third person controller using this structure (character, rigidbody, moves from FixedUpdate() and Camera moves in LateUpdate()) and everything is running absolutely smoothly. However, I've included a first-person mode in which the camera rotates up and down on it's 'transform.right' and rotates left to right on 'Vector3.up'. I position the camera at the characters head and when the camera rotates left or right, the characters looks in the same direction as the camera.

    The system I'm using has an empty transform, at (0,0,0) rotate along with the camera (only on its y-rotation) and the character uses these rotations. So this has the character turn along with the camera whenever it is rotated left to right.

    The problem is that, whenever the character is moving and I rotate the camera left or right it starts to jitter. While the character is still or if the camera moves up or down at any point, it works perfectly fine. The characters movement is set in FixedUpdate() and the camera, empty transform and characters rotation are set in LateUpdate(). I've tried many combinations of different Update() and it only gets worse with other combinations.

    The character uses a Rigidbody with the Interpolate turned on and is not kinematic. The code that the camera uses to rotate left-right is:

    Code (CSharp):
    1. this.transform.RotateAround (this.transform.position, Vector3.up, zLeftX * 2f);
    Where 'zLeftX' is the Horizontal input of the right analog stick. The position that the camera uses is the head transform of the character. I've also tried parenting the camera to the character and rotating the character rather than the camera but it makes no difference.

    I've checked to see if there is any other area in the scripts that is messing with the rotations/positions but I can confirm that it's not the case. Any suggestions?
     
  2. bigmisterb

    bigmisterb

    Joined:
    Nov 6, 2010
    Posts:
    4,221
    I dont think you are giving enough info on this. Can you post the two methods you are talking about?

    I usually dont use RotateAround like you have there. I usually use Rotate. If I feel frisky, I even use Rotate with Space.Self. I think the problem is that we can't see what your doing.

    Also, I generally use Time.deltaTime to do rotations like this.
    Code (csharp):
    1.  
    2. transform.Rotate(Vector3.up, zLeftX * 360f * Time.deltaTime, Space.Self);
    3.  
    If this still jitters, try moving it to OnPreRender.
     
    Jakeiiii likes this.
  3. Jakeiiii

    Jakeiiii

    Joined:
    Jul 7, 2014
    Posts:
    256
    Trying that rotation idea and moving it to OnPreRender didn't work, unfortunately.

    Here's what I've got in LateUpdate() run after the camera has done the rotation:

    Code (CSharp):
    1. relative.transform.rotation = new Quaternion (0f, cam.transform.rotation.y, 0f, cam.transform.rotation.w);    //setting the empty transform to have the same rotation as the camera on the y-axis
    2.  
    3. this.transform.forward = relative.transform.forward; //setting the character to have the same rotation
    Here's what I've got in FixedUpdate() to move the character:

    Code (CSharp):
    1. newDir = Vector3.Normalize(direction);   //direction is Vector3(horizontal Input, 0f, vertical Input)
    2. newDir *= Vector3.Magnitude(direction);
    3.  
    4. if(Vector3.Magnitude(direction) > accel)     //Acceleration system
    5.     accel = Mathf.Lerp(accel, Vector3.Magnitude(new Vector3(newDir.x,0f,newDir.z)), Time.fixedDeltaTime * acceleration);
    6. else
    7.     accel = Vector3.Magnitude(new Vector3(newDir.x,0f,newDir.z));
    8.                  
    9.  rb.velocity = Vector3.Lerp (rb.velocity, new Vector3 (0f, rb.velocity.y * addedSpeed, 0f) +
    10.                                                 (newDir.z * relative.transform.forward * currentSpeed) +
    11.                                                 (newDir.x * relative.transform.right * currentSpeed), accel * Time.fixedDeltaTime * 4f);
     
  4. bigmisterb

    bigmisterb

    Joined:
    Nov 6, 2010
    Posts:
    4,221
    You need to use a numeric controlled camera. I think you are going too far out of the box.

    This is something I threw together. It is an orbital/first person camera controller. I put in the parts to control looking of the head, but I am sure that part will need to be adjusted for you.

    Code (csharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using System.Collections.Generic;
    4.  
    5. public class CameraController : MonoBehaviour {
    6.     public Transform head;
    7.  
    8.     public float minY = -60;
    9.     public float maxY = 60;
    10.  
    11.     public float maxDistance = 10;
    12.     public float camCollisionOffset = 1;
    13.  
    14.     public float sensitivityX = 15;
    15.     public float sensitivityY = 15;
    16.     public float sensitivityZ = 15;
    17.  
    18.     private float currentDistance = 0;
    19.     private float cameraDistance = 0;
    20.     public float x, y;
    21.  
    22.     void Start(){
    23.         if (head == null)
    24.             return;
    25.  
    26.         // preset x and y from the euler
    27.         Vector3 euler = head.eulerAngles;
    28.         x = euler.y;
    29.         y = euler.x;
    30.     }
    31.  
    32.     void LateUpdate(){
    33.         if (head == null)
    34.             return;
    35.  
    36.         // get the inputs and apply them to x and y.
    37.         x += Input.GetAxis ("Mouse X") * sensitivityX;
    38.         y -= Input.GetAxis ("Mouse Y") * sensitivityY;
    39.  
    40.         // clamp the y to prevent gimbal lock.
    41.         y = ClampAngle (y, minY, maxY);
    42.  
    43.         // adjust the distance from the scroll wheel.
    44.         currentDistance -= Input.GetAxis("Mouse ScrollWheel") * sensitivityZ;
    45.  
    46.  
    47.         // move the camera to the head.
    48.         transform.position = head.position;
    49.  
    50.         // set the rotation from the new euler angles
    51.         Vector3 euler = new Vector3(y, x, 0);
    52.         transform.eulerAngles = euler;
    53.  
    54.         // preset the distance we want to be at.
    55.         float distance = currentDistance;
    56.  
    57.         // if we are farther than the first person look allows
    58.         // get the collision if we can.
    59.         // set the distance to that collision.
    60.         // notice that we are using the camCollisionOffset so that we don't do funky snapping.
    61.         if (currentDistance > camCollisionOffset) {
    62.             Ray ray = new Ray (transform.position, -transform.forward);
    63.             RaycastHit hit;
    64.             if(Physics.Raycast(ray, out hit, currentDistance + camCollisionOffset)){
    65.                 distance = hit.distance - camCollisionOffset;
    66.             }
    67.         }
    68.  
    69.         // lerp the camera over time to smooth movment.
    70.         // note we are using a second variable to actually do the moving.
    71.         cameraDistance = Mathf.Lerp(cameraDistance, distance, 5 * Time.deltaTime);
    72.  
    73.         // move the camera back the distance required.
    74.         transform.Translate (Vector3.back * distance);
    75.  
    76.         // if we are close enough to the head, rotate the head with the camera
    77.         if (cameraDistance < camCollisionOffset) {
    78.             head.rotation = Quaternion.Lerp (head.rotation, transform.rotation, 5 * Time.deltaTime);
    79.         }
    80.     }
    81.  
    82.     // clamping an angle helps gimbal lock on the camera
    83.     float ClampAngle(float angle, float from, float to) {
    84.         if(angle > 180) angle = 360 - angle;
    85.         angle = Mathf.Clamp(angle, from, to);
    86.         return angle;
    87.     }
    88. }
     
    Jakeiiii likes this.
  5. Jakeiiii

    Jakeiiii

    Joined:
    Jul 7, 2014
    Posts:
    256
    Sorry but your code didn't make a difference... and I'm not quite sure how it works. You're setting the camera's rotation to lerp to the head's rotation but I don't see where the head rotates?
     
  6. Jakeiiii

    Jakeiiii

    Joined:
    Jul 7, 2014
    Posts:
    256
    I think the problem is to do with rotating the character, rather than the camera.
     
  7. Jakeiiii

    Jakeiiii

    Joined:
    Jul 7, 2014
    Posts:
    256
    Still no solution as of yet.
    It's just having a camera keep up with a rigidbody mainly. Does anyone have any ideas? No bad ideas. :))
     
  8. _OK_

    _OK_

    Joined:
    Oct 3, 2014
    Posts:
    33
    i use FixedUpdate() for camera movement because of this problem - i know the docs say late update but i get jitter with late update and no jitter in fixed update. Seems to be a problem with smooth follow on rigid body

    try this code below for camera - i use this for a cockpit inside a plane - the higher the smooth time value the smoother and slower the camera movement

    Code (CSharp):
    1. public class CameraController : MonoBehaviour {
    2.     public GameObject target;
    3.     public Camera cameraCockpit;
    4.  
    5.     private float x = 0f;
    6.     private float y = 0f;
    7.     private float xSmooth = 0f;
    8.     private float ySmooth = 0f;
    9.     public float smoothTime = 0.8f;
    10.     private float ySpeed = 0.0f;
    11.     private float xSpeed = 0.0f;
    12.     private Quaternion rotateCam;
    13.     private Quaternion lookDirection;
    14.  
    15.     public bool getLookAroundCockpitActive;
    16.     public bool setLookAroundCockpitActive = false;
    17.     private bool lookbuttonPressed = false;
    18.  
    19.     void Start()
    20.     {
    21.  
    22.     }
    23.  
    24.     void LateUpdate()
    25.     {
    26.         if(target)
    27.         {
    28.             transform.position = target.transform.position;
    29.         }
    30.     }
    31.  
    32.     public void ActiveCockpitCamera(){
    33.  
    34.         if(cameraCockpit.enabled){
    35.  
    36.             cameraCockpit.enabled = false;
    37.         }else{
    38.             cameraCockpit.enabled = true;
    39.         }
    40.     }
    41.  
    42.  
    43.     public void setlookAround(bool lookbool){
    44.  
    45.         setLookAroundCockpitActive = lookbool;
    46.  
    47.     }
    48.  
    49.     void FixedUpdate()
    50.     {
    51.         if (target && cameraCockpit)
    52.         {
    53.             if (setLookAroundCockpitActive == true && cameraCockpit.enabled)
    54.             {
    55.  
    56.                 lookbuttonPressed = true;
    57.  
    58. //                for (var i = 0; i < Input.touchCount; ++i) {
    59. //
    60. //                    x += Input.GetTouch(i).deltaPosition.x * 0.1f;
    61. //                    y -= Input.GetTouch(i).deltaPosition.y * 0.1f;
    62. //
    63. //                }
    64.  
    65.                 x += Input.GetAxis ("Mouse X") * 0.2f;
    66.                 y -= Input.GetAxis ("Mouse Y") * 0.2f;
    67.  
    68.  
    69.             }
    70.  
    71.             x = ClampAngle(x, -20, 20);
    72.             y = ClampAngle(y, -20, 10);
    73.  
    74.             xSmooth = x;
    75.             //xSmooth = Mathf.SmoothDamp(xSmooth, x, ref xSpeed, 0f);
    76.             ySmooth = Mathf.SmoothDamp(ySmooth, y, ref ySpeed, smoothTime);
    77.  
    78.             rotateCam = Quaternion.Euler(ySmooth, xSmooth, 0);
    79.  
    80.             lookDirection = transform.rotation * rotateCam;
    81.             transform.rotation = Quaternion.Slerp(lookDirection, target.transform.rotation, 0.3f);
    82.  
    83.             if (setLookAroundCockpitActive == false && lookbuttonPressed == true)
    84.             {
    85.                 x = 0;
    86.                 y = 0;
    87.                 lookbuttonPressed = false;
    88.             }
    89.         }
    90.     }
    91.  
    92.     float ClampAngle(float angle, float min, float max)
    93.     {
    94.         if(angle < -360)
    95.             angle += 360;
    96.         if(angle > 360)
    97.             angle -= 360;
    98.         return Mathf.Clamp(angle, min, max);
    99.     }
    100. }
     
  9. _OK_

    _OK_

    Joined:
    Oct 3, 2014
    Posts:
    33
    Actually looking again at your code your problem might be that you put all code in late update when you should just put the transform position (camera) in late update and everything else in fixed update
     
    jsmilton05 likes this.
  10. Ysgramor

    Ysgramor

    Joined:
    Jan 23, 2014
    Posts:
    69
    the jitter appeared because ure moving ur character rigidbody in fixed update based on late update relative.transform.foward

    i think it'll fix when u move that code before u moving the rb

    maybe like this:
    input>direction>rigidbody>then cam position after animation
     
    DarthMurky likes this.
  11. jsmilton05

    jsmilton05

    Joined:
    Jan 26, 2017
    Posts:
    1
    I was having the same problem, this fixed it for me.
     
    DarthMurky likes this.