- Home /
How do I fix jitter?
So I'm currently making a rigidbody fps controller and I'm getting this jitter that comes in spurts. It's not horrible but becomes very bad when switching to slow motion. The jitter only happens when I'm walking around and looking at an object. The player is already interpolated as well.
Here's my player script:
public class PlayerController : MonoBehaviour
{
//Components
private Animator anim;
private Rigidbody rb;
//Movement
Vector3 movement;
//Speed and Sprinting
private bool sprinting;
private float speed;
public float sprintSpeed = 750f;
public float walkSpeed = 500f;
public float stamina, maxStamina;
public bool usingStamina;
//Jump and Grouncheck
public float jumpForce;
public bool isGrounded;
public Transform groundCheck;
public float groundDistance = 0.4f;
public LayerMask whatIsGround;
public Vector3 airControl;
public float airControlForce;
// Start is called before the first frame update
void Start()
{
rb = GetComponent<Rigidbody>();
anim = GetComponent<Animator>();
}
// Update is called once per frame
void Update()
{
movement.x = Input.GetAxisRaw("Horizontal") ;
movement.z = Input.GetAxisRaw("Vertical");
movement.Normalize();
isGrounded = Physics.CheckSphere(groundCheck.position, groundDistance, whatIsGround);
if (isGrounded)
{
Jump();
}
Sprint();
}
private void FixedUpdate()
{
if (isGrounded)
{
rb.velocity = rb.rotation * new Vector3(movement.x * speed * Time.deltaTime, rb.velocity.y, movement.z * speed * Time.deltaTime);
}
if (!isGrounded)
{
rb.AddRelativeForce(movement.x * airControlForce, 0f, movement.z * airControlForce);
}
}
private void Jump()
{
if (Input.GetKeyDown(KeyCode.Space))
{
rb.AddForce(jumpForce * transform.up);
}
}
private void Sprint()
{
speed = walkSpeed;
if (isGrounded)
{
if(Input.GetKeyDown(KeyCode.LeftShift))
{
sprinting = true;
}
}
if (Input.GetKeyUp(KeyCode.LeftShift))
{
sprinting = false;
}
if(usingStamina)
{
if (sprinting && stamina >= 0f)
{
speed = sprintSpeed;
stamina -= Time.deltaTime;
}
else if (!sprinting && stamina < maxStamina)
{
stamina += Time.deltaTime;
}
}
else if(sprinting)
{
speed = sprintSpeed;
}
}
private void OnDrawGizmos()
{
Gizmos.DrawWireSphere(groundCheck.position, groundDistance);
}
}
And here's my camera script:
public class CameraController : MonoBehaviour
{
public Vector2 mouseLook;
[Range(0.0f, 100f)]
public float sensitivity;
private GameObject character;
private Rigidbody rb;
void Start()
{
Cursor.lockState = CursorLockMode.Locked;
Cursor.visible = false;
character = transform.parent.gameObject;
rb = character.GetComponent<Rigidbody>();
}
private void LateUpdate()
{
mouseLook.x += Input.GetAxis("Mouse X") * sensitivity;
mouseLook.y += Input.GetAxis("Mouse Y") * sensitivity;
mouseLook.y = Mathf.Clamp(mouseLook.y, -90f, 90f);
transform.localRotation = Quaternion.AngleAxis(-mouseLook.y, Vector3.right);
rb.MoveRotation(Quaternion.AngleAxis(mouseLook.x, rb.transform.up));
}
}
I'm going to assume it has something to do with updates vs fixed updates but I can't figure out what I did wrong.
Hi, looking at your code: some physics related code is called in Update, not in FixedUpdate and this will lead to bugs at high framerates. Example: on a situation where Update is called 2 times between 2 FixedUpdates (game at 120Hz, physics at 60Hz, or game & physics at 60Hz but timeScale at 0.5): the "jump" code can be called twice (during 2 consecutive Update) before the next FixedUpdate, the player will then jump higher (2 calls to AddForce before physics are resolved). The jitter might not be linked to that though, but those problems should be fixed first :-)
EDIT: my bad: GetKeyDown should avoid the double jump (except if it's possible to press the key faster than 2 physics update). Though, even if it works, it's not very "clean"
Answer by FlaSh-G · Aug 17, 2020 at 09:49 AM
Edit
ait a second, I overlooked that this is a first person camera. LateUpdate (as well as Update, by the way) should work fine. However, you are mixing camera controls with controls for the rigidbody.
Rigidbody interpolation means that between two FixedUpdates, the object is interpolated between the second latest FixedUpdate result and the latest. So if you had, say, ~3 frames between two FixedUpdates (which is what you have at 144 fps), the object moves in 3 steps from the previous position to the current one.
Now, if you were to interfere in that interpolation by doing stuff with the rigidbody, I could imagine that things could get hairy. Although you're doing movement in FixedUpdate and only rotation in Update, I could, for example, imagine that rotation interpolation could get into conflict with rotation applied in Update.
Original answer
ere, have this article: http://blog.13pixels.de/2019/what-exactly-is-fixedupdate/
In it, there's a script linked that you can use: https://gist.github.com/FlaShG/2ee9ca42492363f25b1c416ac85b0732
In short: Move the camera in FixedUpdate as well and interpolate it with that script. If you still get jitter, interpolate your rigidbody with that script as well (and turn interpolation off on the rb itself).
Your answer
Follow this Question
Related Questions
Game not running properly on slow machines (low fps) 1 Answer
Collision Detection on Rigidbody with Interpolation and Rigidbody with Extrapolation is different 0 Answers
Rigidbody character and Update() function 1 Answer
Is it okay to use ForceMode.VelocityChange in Update()? 1 Answer
Slow motion all but one - yet another round, hopefully the last 6 Answers