Making a bool stay true for a second/while animation is playing

Hello,
I’m a beginner at Unity, and am attempting to make a 2D Platform game. I’m making the Attacking Script for the player, but the problem is, I don’t want the character to move at all when the player hits the attack button. As an example, I’ve set it up something like this:

The PlayerController script:

using UnityEngine;
using System.Collections;

public class PlayerController : MonoBehaviour {
	
	public Rigidbody2D rb;
	public Animator anim;
	public float speed;
	public float jumpHeight;
	public Transform groundCheck;
	public LayerMask whatIsGround;
	public AttackController attackController;

	private bool stab;
	private bool upSwing;
	private bool downSwing;
	private bool sideSwing;
	private bool guarding;

	float groundRadius = 0.2f;
	public bool grounded = false;
	bool facingRight;

	void Start () {
	
		rb = GetComponent<Rigidbody2D> ();
		anim = GetComponent<Animator> ();
		facingRight = true;
		attackController = GameObject.Find ("Player").GetComponent<AttackController>();
	}
	

	void FixedUpdate () {

		float move = Input.GetAxis ("Horizontal");
		stab = attackController.stab;
		upSwing = attackController.upSwing;
		downSwing = attackController.downSwing;
		sideSwing = attackController.sideSwing;

		if (!sideSwing) {
		
				if (move != 0 && grounded) {
					rb.velocity = new Vector2 (move * speed, rb.velocity.y);
					anim.SetBool ("IsWalking", true);
				} else {
					anim.SetBool ("IsWalking", false);
				}
			}

And the AttackController script:

using UnityEngine;
using System.Collections;

public class AttackController : MonoBehaviour {

	public Animator anim;
	public Rigidbody2D rb;
	public bool stab;
	public bool upSwing;
	public bool downSwing;
	public bool sideSwing;
	public PlayerController playerController;
	private bool OnGround;

	void Start () {
		anim = GetComponent<Animator> ();
		rb = GetComponent<Rigidbody2D> ();
		playerController = GameObject.Find ("Player").GetComponent<PlayerController>();

	}
	

	void Update () {
if (Input.GetKeyDown (KeyCode.X) && (Input.GetKey (KeyCode.RightArrow) || Input.GetKey (KeyCode.LeftArrow))&& OnGround) {
			anim.SetTrigger ("SideSwing");
			sideSwing = true;
			Debug.Log ("Player is SideSwing");
		} else {
			sideSwing = false;
}

Now the PlayerController script can access the sideSwing bool from AttackController script, so that when sideSwing is true, the movement code will not run. The problem is, when the player has GetKeyDown on the X key, the bool is only true for a single FixedUpdate frame, and can still move while the animation plays from the animator.

Changing it to just GetKey will work, but only if the player is holding down the key, and that’s unnecessary in a platformer. I’ve been considering putting the bool in some kind of loop so that it stays true for a limited time, like one second or even the animation clip. But because I’m using an Animator I don’t know how to get the length of the current animation being played. I also don’t know how to make the bool stay in a time loop without using coroutines, and I’m not sure how to implement that.

Perhaps there’s a simpler way to do this, and I’m not seeing it.

Why don’t you want to use a coroutine to keep your bool true for 1 second?
Otherwise in the animation window you could have your “swing” animation set a bool to true when it starts and set it back to “false” when it ends.

Coroutines are very interesting tools and are not complicated.

You can write a coroutine as below:

private IEnumerator SideSwingCo()
{
	sideSwing = true;
	anim.SetTrigger ("SideSwing");
	// Wait for 1 second
	yield return new WaitForSeconds(1);
	sideSwing = false;
}

Then your Update method becomes:

void Update () {
	if (Input.GetKeyDown (KeyCode.X) && (Input.GetKey (KeyCode.RightArrow) || Input.GetKey (KeyCode.LeftArrow))&& OnGround) {
		StartCoroutine(SideSwingCo());
 }

I would advice to don’t reset sideSwing in else part of your code in AttackController.cs. Instead use animation events to call a function on animation completion and set sideSwing to false there.

AttackController.cs

public void OnSideSwingCompletion()
{
    sideSwing = false;
}

void Update () {
 if (Input.GetKeyDown (KeyCode.X) && (Input.GetKey (KeyCode.RightArrow) || Input.GetKey (KeyCode.LeftArrow))&& OnGround) {
             anim.SetTrigger ("SideSwing");
             sideSwing = true;
             Debug.Log ("Player is SideSwing");
         } 
 }

Now Select you game object and goto Animation tab select last frame and press Add Event button and pick the function OnSideSwingCompletion.

Another thing you should probably consider that when you set state in PlayerController.cs script as:

anim.SetBool ("IsWalking", false);

Do not forget to set the velocity of rigid body to zero, otherwise it may keep moving as per the applied force.

anim.SetBool ("IsWalking", false);
rb.velocity = Vector3.zero;

Hope it helps!