0
\$\begingroup\$

I'm trying to get a Skeleton Model to go from its walking animation to its idle animation using a bool that checks for input. Currently, in-game, the skeleton doesn't leave its walking animation and stays in it even when not walking.

Here is the code I'm using:

public class SkeletonMove : MonoBehaviour
{
    private float velocity = 5f;
    public bool _isWalking = false;
    Vector2 input;

    void Update()
    {
        GetInput();

        if (Mathf.Abs(input.x) < 1 && Mathf.Abs(input.y) < 1) 
            return;

        Rotate();
        Move();
    }

    void GetInput()
    {
        input.x = Input.GetAxisRaw("Horizontal");
        input.y = Input.GetAxisRaw("Vertical");
    }

    void Move()
    {
        _controller.Move(transform.forward * velocity * Time.deltaTime);
        _anim.SetBool("Walking", _isWalking);

        if (input.x != 0 || input.y != 0)
            _isWalking = true;

        if (input.x == 0 && input.y == 0)
            _isWalking = false;
    }
New contributor
Edi Ekwere is a new contributor to this site. Take care in asking for clarification, commenting, and answering. Check out our Code of Conduct.
\$\endgroup\$
  • 2
    \$\begingroup\$ Don't forget to show us how you've set up the transitions in your animation control graph too! \$\endgroup\$ – DMGregory Jan 14 at 12:42
1
\$\begingroup\$

Welcome to the GameDev Stack Exchange.

As other users pointed out, GetAxisRaw returns values in the range of [-1, 1] which means if a user (or skeleton in your case) is not holding down both keyboard buttons or a joystick in the exact correct position, you will be returning values less that 1 or greater than -1. This will cause your animation code to return earlier than you probably planned. I believe this is the main source of your problem.

However I think there is another issue with your code. If you take a close look at your Move() function, you will see that you are actually updating your animators Bool before you update the value of _isWalking. This means any update you send to your animator will be 1 update frame late, and if you are short circuiting (returning earlier to avoid running additional extra code) you may never pass the correct value into your animator.

These problems often pop up a lot and can be confusing to new game programmers, so I would suggest you look into adding code like Debug.Log("My current input is: " + input.x + ", " + input.y); in places you think might be going wrong. If your case Debug.Log("Setting animation controller Walking bool to: " + _isWalking); would help you know when and if you are sending your updates to the animation controller.

Here is slightly updated version of your script that I think will help fix your issues. It might have some compile errors (sorry I didn't test it) but I think you can probably get it working without too much trouble.

public class SkeletonMove : MonoBehaviour
{
    private float velocity = 5f;
    public bool _isWalking = false;
    public bool debugMode = false; // normally you don't want this kind of code here long term, this is just an example

    private void Update()
    {
        Vector2 input GetInput();

        if (Mathf.Abs(input.x) == 0 && Mathf.Abs(input.y) == 0)
        {
            StopMoving();
        }
        else
        {
            Rotate(input);
            Move(input);
        }
    }

    private Vector2 GetInput()
    {
        Vector2 input = Vector2.zero;
        input.x = Input.GetAxisRaw("Horizontal");
        input.y = Input.GetAxisRaw("Vertical");

        if (debugMode)
        {
            Debug.LogFormat("Skeleton {0} Input Update: {1}, {2}", gameObject.name, input.x, input.y);
        }

        return input;
    }

    private void Move(Vector2 input)
    {
        Vector3 movement = new Vector3(input.x, input.y, 0.0f);
        movement.Normalize();
        _controller.Move(movement * velocity * Time.deltaTime);
        
        _isWalking = input.x != 0 && input.y != 0;

        if (debugMode)
        {
            Debug.LogFormat("Skeleton {0} {1} Movement Update: {2}, {3}", gameObject.name, _isWalking ? "Walking" : "Sitting", movement.x, movement.y);
        }

        _anim.SetBool("Walking", _isWalking);
    }
}

Normally I wouldn't recommend this extra "debugMode" stuff, but I'm guessing you might be new to programming so it may be helpful for you to use this kind of style to help debug issues and keep track of how things work until you are more used to working with Unity and some of it's weird quirks. If you run into some really tough issues you may also want to look into using "breakpoints" so you can check your code line by line to see where parts may be failing or acting in seemingly unpredictable ways.

\$\endgroup\$
  • \$\begingroup\$ Thanks for letting me know about Debugs. I am a beginner so I underestimated how important they are. Thanks for your help. I managed to figure out a way to do it based on your example. I'll remember to use Debugs in the future. \$\endgroup\$ – Edi Ekwere 2 days ago
  • \$\begingroup\$ No problem, glad we could help. Just bear in mind that Debug functions are actually very slow. For simple projects, prototypes, and experiments this is probably not an issue, but when you begin working on more real projects (ones you plan to release) you will want to remove these. It might also be a good idea to remove ones from parts of the code you don't plan on changing and know works just to keep the console window a bit cleaner and easy to read. \$\endgroup\$ – Benjamin Danger Johnson 2 days ago
-1
\$\begingroup\$

You are returning if the value is less than 1. That's why you can not enter into your Move() functions hence you can not enter into below code.

if (input.x == 0 && input.y == 0)
{
   _isWalking = false;
}

Try to debug your code.

\$\endgroup\$

Your Answer

Edi Ekwere is a new contributor. Be nice, and check out our Code of Conduct.

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.