Player is jittering with high FPS

Hello guys,

I’m just starting to learn game development with Unity and I’m trying to understand the following issue that is happening:

I have a basic 2D scene with a character and some tiles (all from the asset store) and a Cinemachine camera that is set to follow the character. The thing is, when I play the game in the editor and the FPS are high (600-700 says the “stats” window) the character jitters when running and jumping. However, after some minutes normally the FPS drops to 60-70 and the jitter stops. If I build and run the game, the jitter does not happen.

Here are two videos for reference:

I would like to know:

  • What causes the drop in FPS? It seems random because it does not always happen after playing in the editor.
  • Why is jittering playing in the editor but not in the game build.

Thank you!

What version of Unity are you using?
Does the jitter happen if you close the inspector?

can you show your movement script? if you havent resolved it already

One thing to note here is that if this is Rigidbody2D movement then the Rigidbody2D doesn’t have interpolation activated therefore the Transform will only ever update when the simulation runs which, by default, is 50Hz.

I’m using 2021.3.16 LTS. Right now the jitter is not happening. However, It would be great to know what was causing it. Maybe is my computer? It’s a 2019 MacBook Pro i9 16GB.

Sure, here is the player controller.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;

public class PlayerController : MonoBehaviour
{
    [SerializeField] private float moveSpeed = 8f;
    [SerializeField] private float jumpForce = 16f;
    [SerializeField] private float groundCheckRadius = 0.2f;
    [SerializeField] private float fallingThreshold = -0.1f;

    [Space(20)]

    [SerializeField] private Rigidbody2D rigidBody;
    [SerializeField] private Transform groundCheck;
    [SerializeField] private LayerMask groundLayer;
    [SerializeField] private Animator animator;
    [SerializeField] private PlayerAttackController attackController;

    private float _moveDirection;

    private bool _jump;
    private bool _isGrounded;

    private bool _attack;
    private bool _isAttacking;

    private bool _isFacingRight = true;

    // User inputs
    public void Move(InputAction.CallbackContext context)
    {
        _moveDirection = context.ReadValue<Vector2>().x;
    }

    public void Jump(InputAction.CallbackContext context)
    {
        if (context.performed && _isGrounded)
        {
            _jump = true;
        }
    }

    public void Attack(InputAction.CallbackContext context)
    {
        if (context.performed && _isGrounded)
        {
            _attack = true;
        }
    }

    void Update()
    {
        if (!_isFacingRight && _moveDirection > 0f)
        {
            Flip();
        }
        else if (_isFacingRight && _moveDirection < 0f)
        {
            Flip();
        }
    }

    void FixedUpdate()
    {
        _isGrounded = Physics2D.OverlapCircle(groundCheck.position, groundCheckRadius, groundLayer);
        _isAttacking = animator.GetBool("PlayerMovementLocked");

        // Move
        if (!_isAttacking)
        {
            rigidBody.velocity = new Vector2(_moveDirection * moveSpeed, rigidBody.velocity.y);
            animator.SetFloat("MoveSpeed", Mathf.Abs(_moveDirection));
        }

        // Jump
        if (_jump && !_isAttacking)
        {
            rigidBody.AddForce(new Vector2(0f, jumpForce), ForceMode2D.Impulse);
            animator.SetBool("IsJumping", true);
            _jump = false;
        }

        if (rigidBody.velocity.y < fallingThreshold)
        {
            animator.SetBool("IsJumping", false);
            animator.SetBool("IsFalling", true);
        }

        if (_isGrounded)
        {
            animator.SetBool("IsFalling", false);
        }

        // Attack
        if (_attack)
        {
            rigidBody.velocity = new Vector2(0f, 0f);
            animator.SetTrigger("Attack");
            attackController.Attack();
            _attack = false;
        }
    }

    private void Flip()
    {
        _isFacingRight = !_isFacingRight;
        Vector3 localScale = transform.localScale;
        localScale.x *= -1f;
        transform.localScale = localScale;
    }
}

See my post above.

Thanks for your response.

I changed Interpolate from None to Interpolate and I think this resolved the issue. Thank you.

1 Like

Yes, it’s important to understand that physics isn’t running per-frame unless you ask for it to do so in the 2D physics settings.

Good luck!