Help with Basic Script to Play Animations

I’m still very new to C# (more of an artist than a coder tbh) and I used a tutorial to get some basic tank controls coded (which I will definitely polish up later)

Now that I’ve made and imported an idle and walk animation, I just want them to play accordingly for now.

I’ve set this up in the animator component for my player (shown in the image), and I just want to script out a logic that goes something like this for the moment: if moveSpeed(that’s the name given to the player’s motion speed) > 0, then play “rig|Walk”. else, play “rig|Idle

This is the code I was instructed to build. (It’s pretty simple and it helped me get an idea of how code structure works)
Note: I noticed the person didn’t put any of this into either a start or update, so bonus points if anyone can help me get those two things implemented into this script.

public class PlayerTankController : MonoBehaviour
{
    [SerializeField] private float moveSpeed = 5f;
    [SerializeField] private float turnSpeed = 400f;

    private CharacterController cc;

    private void Awake()
    {
        cc = GetComponent<CharacterController>();
    }
    private void Update()
    {
        if (Input.GetKey(KeyCode.W))
        {
            cc.Move(transform.forward * moveSpeed * Time.deltaTime);
        }

        if (Input.GetKey(KeyCode.S))
        {
            cc.Move(-transform.forward * moveSpeed * Time.deltaTime);
        }

        if (Input.GetKey(KeyCode.A))
        {
            transform.Rotate(0, -turnSpeed * Time.deltaTime, 0);
        }

        if (Input.GetKey(KeyCode.D))
        {
            transform.Rotate(0, turnSpeed * Time.deltaTime, 0);
        }
    }

   
}

Anyway, my overall question is what would be the best way to get the logic/pseudocode shown below implemented so that my player simply plays the idle animation upon the game running, and the walk when his speed(moveSpeed in our case) is greater than 0?
Not really sure if I should put it into this script shown, or make a new script.

the most basic workflow is by using animator.setbool, say the player is running, animateRun = true, and then in the actual animation tree you would just make the transitions between states and the conditions required for the animation to change, based on whatever bools you have

Unity - Scripting API: Animator.SetBool (unity3d.com)

Another way is to add a float parameter in the animator called “speed”. Then in the transitions between idle and walk, add a condition based on the speed.
Your script sends a speed float value to the animator

animator.SetFloat ("speed", speed);

This speed could also be used for the actual animation state speed multiplier too.


Walk state enters if speed > 0.1
Idle state enters if speed < 0.1

1 Like

I decided to go with this option.

I now have:
(For now, I have the trigger for the “walk” boolean in “KeyCode.W” )

public class PlayerTankController : MonoBehaviour
{
    //Sets the context for "animator" within Animator Component.
    Animator animator;
  
    //Sets the context for walking/not walking.
    bool walk;
    void Start()
    {
        animator = GetComponent<Animator>();
        walk = false;
    }

  

    [SerializeField] private float moveSpeed = 5f;
    [SerializeField] private float turnSpeed = 400f;

    private CharacterController cc;

    private void Awake()
    {
        cc = GetComponent<CharacterController>();
    }
    private void Update()
    {
        if (Input.GetKey(KeyCode.W))
        {
            cc.Move(transform.forward * moveSpeed * Time.deltaTime);
            walk = true;
        }

        else

        {
            walk = false;
        }

        if (walk == false)
        {
            animator.SetBool("rig|Walk", false);
        }

        if (walk == true)
        {
            animator.SetBool("rig|Walk", true);
        }

        if (Input.GetKey(KeyCode.S))
        {
            cc.Move(-transform.forward * moveSpeed * Time.deltaTime);
        }

        if (Input.GetKey(KeyCode.A))
        {
            transform.Rotate(0, -turnSpeed * Time.deltaTime, 0);
        }

        if (Input.GetKey(KeyCode.D))
        {
            transform.Rotate(0, turnSpeed * Time.deltaTime, 0);
        }
    }

  
}

No errors have occurred, but the animations aren’t playing while running the game.
I don’t even know if it’s anything to do with my code because even the idle animation set to play upon entry doesn’t play. The player does assume the general pose for the idle animation, but he is completely motionless.

I have unchecked “Apply Root Motion” (which I’ve seen end up being the problem for other users).
And I’ve made sure “Loop Time” is checked for both idle and walk.

Update!

I have found the reason why none of my animations were play upon running the game.
A key piece of info that I left out, was that the player’s model is its own object inside of the “Player” object itself.

I moved the Animator component to the PlayerModel object and created a whole new script which handles animation within said player’s model; and also deleted everything from the “Player” object’s script that involves any animation.

This is now the script within my PlayerModel which will handle the animation:

public class PlayerAnimation : MonoBehaviour
{
    private Animator animator;

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

    // Update is called once per frame
    void Update()
    {
        if (Input.GetKey(KeyCode.W))
        {
            if (animator != null)
            {
                animator.Play(".rig|Walk");
            }
        }
    }
}

The only problem now is that when the game runs, he only stays in the “idle” state (while stationary) for a certain period of time before automatically going into the walking animation.