2
\$\begingroup\$

My player character vibrates in his idle pose for some reason. He has 3 animations (IdleState, WalkState, RunState) and the latter 2 run smoothly, but when I don't provide directional inputs and he enters his idle state, he looks like he had 100 espresso shots!

43 second video demo here: https://youtu.be/QuHPrkjx-T4

I am not using a blend tree for the moment and the animation used for IdleState was exported with only a single frame (frame 1) from Blender. Unity's FBX import panel has the animation listed as playing from frame 0 to 1. I have tried many different configurations for this animation in the importer, including looping, not looping, matching pose, setting animation length to 0. None of that fixed the jitters (the latter nullified the animation). I have restructured my scripts but have not found a solution for this yet.

My character uses 2 scripts, one to control movement, and another to control animation.

This one controls movement:

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

public class PlayerController : MonoBehaviour {

    private float charSpeed;
    public float walkSpeed;
    private float runSpeed;
    public float jumpForce;
    public CharacterController controller;
    public float gravityScale;
    private Rigidbody rb;

    public static Vector3 moveDirection;

    // Start is called before the first frame update
    void Start() {
        controller = GetComponent<CharacterController>();
        rb = GetComponent<Rigidbody>();
        charSpeed = walkSpeed;
        runSpeed = walkSpeed * 2;

    }

    // Update is called once per frame
    void Update() {

        if (Input.GetButton("Fire3"))
        {
            charSpeed = runSpeed;
        }
        else {
            charSpeed = walkSpeed;
             }

        // Declare movement vector
        moveDirection = new Vector3(Input.GetAxis("Horizontal") * charSpeed,
            moveDirection.y,
            Input.GetAxis("Vertical") * charSpeed);

        // Set y-axis movement conditions (jumping, grounded, free-fall)
        if (Input.GetButton("Jump") && controller.isGrounded){
            moveDirection.y = jumpForce;
        }
        else if (!controller.isGrounded)
        {
            moveDirection.y = moveDirection.y + Physics.gravity.y * gravityScale * Time.deltaTime;
        }
        else
        {
            moveDirection.y = 0;
        }

        // rotated 45 deg to align controls to camera instead of world space:
        Vector3 rotated = Quaternion.Euler(0,-45,0) * moveDirection;
        controller.Move(rotated * Time.deltaTime);

        Vector3 lookDir = new Vector3(rotated.x, 0, rotated.z);

        if (lookDir != Vector3.zero)
        {
            transform.rotation = Quaternion.LookRotation(lookDir);
        }
    }
}

...and this one plays the animations:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;

public class CharacterAnimator : MonoBehaviour
{

    private Rigidbody rb;
    Animator animator;

    void Start()
    {
        rb = GetComponent<Rigidbody>();
        animator = GetComponent<Animator>();

    }

    void FixedUpdate() // was Update(), no change
    {
        if (Input.GetAxis("Horizontal") == 0 && Input.GetAxis("Vertical") == 0)
        {
            animator.Play("IdleState");
        }
        else
        {
            if (Input.GetButton("Fire3"))
            {
                animator.Play("RunState");
            }
            else
            {
                animator.Play("WalkState");
            }
        }
    }
}

What is causing this jittery idle state bug?

\$\endgroup\$
7
  • 1
    \$\begingroup\$ +1 for the addition of the link to a video! Now questions: why do you control the movements in update and the animation in fixedUpdate? Can this cause weirdness? What is the purpose of the while in the animation component (instead of an if)? \$\endgroup\$
    – Vaillancourt
    Commented Jul 14, 2019 at 12:35
  • \$\begingroup\$ Oh, I just changed it from an if to a while before posting and it caused an infinite loop. I forgot to change it back before I posted (let me fix that real quick). I also just tried changing it to "FixedUpdate" an hour ago just to see if it did anything. I am literally trying everything to fix the problem because I don't have a lot of Unity experience, this is my first solid, presentable project \$\endgroup\$ Commented Jul 14, 2019 at 13:01
  • \$\begingroup\$ So none of that is causing the jitter problem because it was a problem before \$\endgroup\$ Commented Jul 14, 2019 at 13:12
  • \$\begingroup\$ Why are you trying to do the animator's job by telling it what animation to play every physics step, instead of just setting its state variables and letting the animation control graph handle the animation state transitions the way it's designed to? \$\endgroup\$
    – DMGregory
    Commented Jul 14, 2019 at 14:46
  • \$\begingroup\$ Try changing the Horizontal and Vertical check to < 0.1 Sometimes when GetAxis returns the value it can be just over 0, for example it can be 0.02345 and that could cause some jittering since it is not exactly 0. If that doesn't do the trick then I would like to see the animator setup as it is playing. I second the advice to setup transitions and parameters in the animator rather than physics update, you can still feed the parameters value here though \$\endgroup\$ Commented Jul 14, 2019 at 15:05

1 Answer 1

1
\$\begingroup\$

SOLVED (technically; it would still be better for me to set animations to be run by the animator instead of script):

I set the animation play speed to 0 for the IdleState and that eliminated the jittery-ness during the IdleState animation. This worked because that animation only has one frame:

enter image description here

IMPORTANT NOTE: I had to get rid of the transitions (connections between states in the Animator panel) because it was causing my animations to not loop under my current setup. Now everything is smooth-running...and smooth-walking...and smooth-standing.

enter image description here

\$\endgroup\$
2
  • \$\begingroup\$ I notice your Parameters section is empty, leading me to suspect that your animation transitions are all unconditional. ie. Rather than waiting for a parameter to take a particular value before transitioning, you've effectively told the animator to follow the arrow into the next state as early as it can. Say, immediately at the end of frame 1 in your idle case, leading to the jitter you saw. A better solution here is to set up your control graph with parameters to control the transitions, and drive the state by setting those parameters, not manually overriding the animation once per update. \$\endgroup\$
    – DMGregory
    Commented Jul 15, 2019 at 9:45
  • \$\begingroup\$ I have done that today and while controls are now much more responsive, animations are not. I will ask another question later about optimizing my graph and control script (animations are part of PlayerController.cs as of today, no more CharacterAnimator script. I will have to record another demo for you \$\endgroup\$ Commented Jul 16, 2019 at 21:59

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .