Forward and Backward animation keep looping when face to left

When facing left, P1’s forward or backward animation keep looping although button released and stop moving. Appreciate if you can advise how to stop the looping animation, thanks.

A. Speed of Backward and Forward from both Layers are 1.

B. Both layers sharing same forward and backward animation

C. Transitions:

                 Conditions| Base |Flip      

idle > forward = forward | true | false

forward > idle = forward |false | true

                 Conditions| Base |Flip      

idle > backward = Backward | true | false

backward > idle = Backward |false | true

private Animator Anim;

[SerializeField] public float WalkSpeed = 0.05f;

private bool IsJumping = false;

private AnimatorStateInfo Player1Layer0;

private bool CanWalkLeft = true;

private bool CanWalkRight = true;

public GameObject Player1;

public GameObject Opponent;

private Vector3 OppPosition;

private bool FacingLeft = false;

private bool FacingRight = true;

// Start is called before the first frame update

void Start()

{

    Anim = GetComponentInChildren<Animator>();

    StartCoroutine(FaceRight());

}

// Update is called once per frame

void Update()

{

    // listen to the animator

    Player1Layer0 = Anim.GetCurrentAnimatorStateInfo(0);

    // Screen border set up (X axis)

    Vector3 ScreenBounds = Camera.main.WorldToScreenPoint(this.transform.position);

    if(ScreenBounds.x > Screen.width - 70)

    {

        CanWalkRight = false;

    }

    if (ScreenBounds.x < 50)

    {

        CanWalkLeft = false;

    }

    else if (ScreenBounds.x > 50 && ScreenBounds.x < Screen.width - 70)

    {

        CanWalkRight = true;

        CanWalkLeft = true;

    }

    //get the opponent's position

    OppPosition = Opponent.transform.position;

    //facing left or right of the Opponent

    if(OppPosition.x > Player1.transform.position.x)

    {

        StartCoroutine(FaceLeft());

    }

    if (OppPosition.x < Player1.transform.position.x)

    {

        StartCoroutine(FaceRight());

    }

    // Walking left and right

    if (Player1Layer0.IsTag("Motion"))

    {

        if (Input.GetAxis("Horizontal") > 0)

        {

            if (CanWalkRight == true)

            {

                Anim.SetBool("forward", true);

                transform.Translate(WalkSpeed, 0, 0);

            }

        }

        if (Input.GetAxis("Horizontal") < 0)

        {

            if (CanWalkLeft == true)

            {

                Anim.SetBool("backward", true);

                transform.Translate(-WalkSpeed, 0, 0);

            }

        }

    }

    if (Input.GetAxis("Horizontal") == 0)

    {

        Anim.SetBool("forward", false);

        Anim.SetBool("backward", false);

    }

    // Jumping once and bending

    if (Input.GetAxis("Vertical") > 0)

    {

        if (IsJumping == false)

        {

            IsJumping = true;

            Anim.SetTrigger("jump");

            StartCoroutine(jumpPaused());

        }

       

    }

    if (Input.GetAxis("Vertical") < 0)

    {

        Anim.SetBool("bend", true);

    }

    if (Input.GetAxis("Vertical") == 0)

    {

        Anim.SetBool("bend", false);

    }

}

IEnumerator jumpPaused()

{

    yield return new WaitForSeconds(.5f);

    IsJumping = false;

}

IEnumerator FaceLeft()

{

    if (FacingLeft == true)

    {

        FacingLeft = false;

        FacingRight = true;

        yield return new WaitForSeconds(0.15f);

        Player1.transform.Rotate(0, -180, 0);

        Anim.SetLayerWeight(1, 0);

    }

}

IEnumerator FaceRight()

{

    if (FacingRight == true)

    {

        FacingRight = false;

        FacingLeft = true;

        yield return new WaitForSeconds(0.15f);

        Player1.transform.Rotate(0, 180, 0);

        Anim.SetLayerWeight(1, 1);

    }

}

}

Alright, I do not know what is causing your issue but here some advice that may help you:

  • Forward/Backward walking should use a float which could be use in a condition like greater than or lower than an +/- epsilon value. An epsilon value is a really small value like 0.01. You then play an idle animation when ever the value is near 0 a.k.a (< epsilon and > -epsilon)
  • You can simplify your “bend” condition to Anim.SetBool(“bend”, Input.GetAxis(“Vertical”) < 0)
  • I’m not really a fan of your FaceLeft/FaceRight function. Why the FaceRight/FaceLeft boolean ? Why Anim.SetLayerWeight ? Is there any reason to wait 0.15f ?
  • You can simplify your CanWalkRight/CanWalkLeft by CanWalkRight = ScreenBounds.x < Screen.width - 70 and CanWalkLeft = ScreenBounds.x > 50
  • It is unclear what drive your jump but you should use physics if possible. You will have more natural jump and you wont required to do a coroutine.
  • You should not use Transform.Translate to make your movement. If you do so, you will not able to have any sort of collision with your player. (If you choose to use Transform.Translate, you should know that you need to multiply by Time.deltaTime to have a smooth movement that does not depends on the frame rate)
  • I wouldnt use the StateMachine of the animator to drive the actual state of the player. (“Motion”) Instead, I would advice you to create your own StateMachine so you can divide your logic. Otherwise, you will find yourself overwhelmed by the amount of code directly in your controller.
  • Use lowerCamelCase nomenclature for your variable. It is pretty much the norm.
  • Sort your variable by visibility. If you feel the need to group them, you might need to subdivide your class as the cohesion in your class is low. In other words, your class is doing to much work.
  • Do not directly expose your variable. (public GameObject Player1) Use C# property. This way you will preserve more control over your data and how other people/class may interact with them.