- Home /
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.
Couldn't you just see if the animation is playing using Animator.GetBool?
Well the animation is played using a trigger, which I prefer to keep that way. But I guess if I need to, I can change it to a bool and do that.
Answer by GiyomuGames · Jul 28, 2015 at 07:43 AM
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 suppose I'm not familiar enough with coroutines to use them. Coroutines go in loops right? Even if coroutines will suspend the bool for a second, if there's a less complex method, I want to try that out first, such as your other suggestion. Thanks!
You should pause, get some coffee or your beverage of choice, and commit to learning Coroutines. They have endless uses and there many really good examples in UA of how to set them up. Yes the first takes time, but you'll be glad you did once you 'get it' and start using them.
I agree with getyour411. 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.Get$$anonymous$$eyDown ($$anonymous$$eyCode.X) && (Input.Get$$anonymous$$ey ($$anonymous$$eyCode.RightArrow) || Input.Get$$anonymous$$ey ($$anonymous$$eyCode.LeftArrow))&& OnGround) {
         StartCoroutine(SideSwingCo());
  }
Thank you! It seems to be working well. I'll take both of your advice and learn more about corountines.
Cool! I updated my initial answer accordingly so you can mark it as correct.
Answer by NeverHopeless · Jul 28, 2015 at 08:45 AM
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!
Thanks, but when I do attempt to add an event, I only functions from the PlayerController script are listed. Do I need to do something else to see the functions of the AttackController script?
Create a function in playercontrollerscript and use Send$$anonymous$$essage function to send a call to attackcontrollerscript.
Your answer
 
 
             Follow this Question
Related Questions
Animation Loop 2 Answers
Animator trigger keeps retriggering. 0 Answers
How to make a 2d animation repeat 1 Answer
how do i make a loop for a boolean? 2 Answers
Double collision on "ground" tagged object results in player thinking they're in air? 1 Answer
 koobas.hobune.stream
koobas.hobune.stream 
                       
                
                       
			     
			 
                