Correcting movement details

Hi,

I have been working on animation and movement programming for my character. Although I have gotten part of what I need, it still lacks work.

I want to show you in the next video what my character looks like in “action”.

At the beginning the character only moves from one side to the other, I think there is no problem with it. Later, he makes a move to get away, from some attack perhaps. I think it lacks some detail.

After that, the character jumps onto platforms. However, it seems to me that the jump is very “slow” and I would like to adjust that. It seems to jump in slow motion.

Also when it falls from the platform, it looks like it is “walking in the air” … I think I can fix that with a ground point.

Before the end, he makes an attack by moving a magic wand, yes, it is a wizard. I have not yet configured the shot or magic.

Finally, the character runs, with a different animation than walking, however, as you can see in the video, it still does not work well. Still, the character stopping the animation continues. I’m still not sure how to stop it, I have not found at what point to configure this.

For this, the character only executes running when his previous state is walking. It cannot run when it is stopped, jumping or shooting. Always run first walk and then run.

In the following code you can see what I have worked on and maybe you can tell me where I can improve my script. I would thank you a lot.

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

public class PlayerMovement : MonoBehaviour
{

    private Rigidbody2D playerRb2d;

    private Animator playerAnimator;

    [SerializeField]
    private float playerWalkSpeed;

    private bool attack;
    private bool isRunning = false;

    public float jumpForce;

    public float playerRunSpeed = 0;
    public float retreatSpeed;
    public float retreatForce;

    private bool facingRight;

    // Revisar doble click variables
    public float timer = 0f;
    public float clickSpeed = 0.5f;

    // Start is called before the first frame update
    void Start()
    {
        facingRight = true;
        playerRb2d = GetComponent<Rigidbody2D>();
        playerAnimator = GetComponent<Animator>();
    }

    // Update is called once per frame
    void FixedUpdate()
    {
        float horizontal = Input.GetAxis("Horizontal");

        HandleMovement(horizontal);

        Flip(horizontal);

        HandleAttack();

        DblClickCheck(horizontal);

        ResetValues();
    }

    void Update() {

        HandleInput();

    }

    private void HandleMovement(float horizontal) {

        if (!this.playerAnimator.GetCurrentAnimatorStateInfo(0).IsTag("Attack"))
        {
            playerRb2d.velocity = new Vector2(horizontal * (playerWalkSpeed + playerRunSpeed), playerRb2d.velocity.y);
        }

        playerAnimator.SetFloat("speedWalk", Mathf.Abs(horizontal));
    }

    private void HandleAttack() {

        if (attack && !this.playerAnimator.GetCurrentAnimatorStateInfo(0).IsTag("Attack"))
        {
            playerAnimator.SetTrigger("attackNormal");
            playerRb2d.velocity = Vector2.zero;
        }
    }

    private void HandleJump() {

        playerRb2d.AddForce(transform.up * jumpForce);
        playerAnimator.SetTrigger("isJumping");
    }

    private void HandleRetreat() {

        if (facingRight)
        {
            playerRb2d.AddForce(Vector2.left * retreatSpeed * retreatForce);
        }
        else if(!facingRight) {
            playerRb2d.AddForce(Vector2.right * retreatSpeed * retreatForce);
        }

        playerAnimator.SetTrigger("isRetreat");
    }

    private void HandleInput() {

        if (Input.GetKeyDown(KeyCode.Q)) {
            attack = true;
        }

        if (Input.GetKeyDown(KeyCode.Space)) {
            HandleJump();
        }

        if (Input.GetKeyDown(KeyCode.E)) {
            HandleRetreat();
        }
    }

    private void DblClickCheck(float horizontal) {

        if (timer < clickSpeed) {

            timer += Time.deltaTime;
        }

        if (Input.GetKeyDown(KeyCode.A) || Input.GetKeyDown(KeyCode.D)) {

            if (timer < clickSpeed)
            {
                playerRunSpeed = 10;
                playerAnimator.SetBool("isRunning", true);
            }
            else {
                playerRunSpeed = 0;
                playerAnimator.SetBool("isRunning", false);
            }

            timer = 0;
        }

    }

    private void Flip(float horizontal) {

        if (horizontal > 0 && !facingRight || horizontal < 0 && facingRight) {

            facingRight = !facingRight;
            Vector3 theScale = transform.localScale;
            theScale.x *= -1;
            transform.localScale = theScale;
        }
    }

    private void ResetValues() {

        attack = false;
        isRunning = false;
    }
}

In the following images, I show you how I have the configuration of the player and the animation tree, focused on the option to run.

And this is what I’m wearing at the moment. Any help or advice would appreciate it.

Greetings!

Hi @Middrel

Check those official animation tutorials… but some tips:

  • As you are animating sprites, make all transitions short.
  • Don’t use has exit time, unless animation needs to play fully.
  • Use “any state” this way you can transition from any state to run (or to any other state for that matter).
  • For extra gravity, modify vertical velocity of Rigidbody2D directly, or add higher gravity to your Rigidbody2D.
1 Like

Hi, @eses thanks for your answers!

  1. Indeed, I am doing the animations. I am doing them with grease pencil from Blender to see how they look. I am not including many pictures, I show you an example. Do you still think I should shorten them further? Only the jump animation was made a little more detailed, so that the jump is not cut. jump-sheet2 hosted at ImgBB — ImgBB

  2. Ok, I work with animation states.

  3. I tried to use “any state”, but I don’t want the running state not to run while jumping. How do I prevent a state from running when I use “any state”?

  4. Ok, I work on the RigidBody to fix this point.

Greetings!

“3. I tried to use “any state”, but I don’t want the running state not to run while jumping. How do I prevent a state from running when I use “any state”?”

Well you can add condition to transition from Any State too? Can’t you?

But here is other way you could do it.

When isWalking is set, you enter walking.
When isRunning is set, you run.

Then just have transitions from all states you need to transition from to isRunning. Here is a quickly sketched state machine, in this case you can enter run from idle, walk or jump, and you can go back from run to idle, walk or jump. You can ignore the any state.

1 Like

Ok … I’m going to rearrange the structure of the transitions, I think that’s where I’m getting a little confused. I work on this point and comment on my results.

Thank you for your comments!