Yield until animation is over?

Hi there!
I’m editing this question for the very last time, to better depict you with my problem, what I’d wanted to do and how I managed to solve it.

The problem I had was very specific: I wanted to create a Progress Bar and let the player press a button to stop its refilling; everytime the refilling would have been stopped, an animation was to be played.

But, since I’m a very flexible demander, I thought I could get along with slightly different results…
So my pretension was just to have different animation played depending on which time the progress bar was stopped, and the best possible outcome for me was to be told how to synchronize perfectly those two things ( Progress Bar and Animations).

So far my question received no answer but a week ago I finally managed to solve this issue by myself, that’s why I thought I could share with you my own solution.

I’ll post that as an answer.

Again, my trouble was ( and I suspect I can safely say that still is) to time the refill of the Progress Bar so that the next refill would wait for the current animation to be finished before starting to fill once more.

So, here is my code so far.
I’m posting this as an answer because it gets the job done as far as I’m concerned, of course this is far from saying it’s the best solution.
Plus I’m a newbie programmer so my code is not fully optimized either.

Instead of leaving this question unanswered, I’m putting my two cents in it.

Two more things to notice: first one, this thing is not perfectly synchronized but it works anyway; second one, the countdown thing I made was just a work out and is not intended to function outside the editor… it’s probably the most confused part of the code and I suggest you to ignore it.

using UnityEngine;
using UnityEditor;
using System.Collections;

public class FinalProgressBar : MonoBehaviour {
	
	/* WHAT IS THIS?
	 * This script handles the behaviours of the Progress Bar... what progress bar? well, I've drawn one with
	 * photoshop but you probably can't see it from where you are.
	 * The purpouse was to make an interactive Progress Bar Minigame similar to the first of Kirby's Fun Pak
	 * ( Megaton Punch)
	 * 
	 * I'm rewriting it ( 3rd time) so that it can be more performant and accurate.
	 * It may turn out messy as it was before, who knows!
	 * 
	 * AS FAR AS I'M CONCERNED, THIS SCRIPT WORKS THE WAY I INTENDED, I'M HAPPY :D
	 * credits? okay: this thing was written by esitoniatteso@gmail.com ( I've stolen some methods hither and thither of course)
	 * 
	 * write me if you want, I can be social!
	 * 
	 * P.S.: of course this thing lacks both a score and a countdown mechanic, and right now is intended to be a
	 * 		 standalone scene ( no menus, no quit, no gameover, just THIS scene here).
	 */
	
	private SpriteRenderer pBT_3;	//I'm trying to reference practically the Images managed by those different SpriteRenderers
	private SpriteRenderer pBT_2;
	private SpriteRenderer pBT_1;
	private SpriteRenderer star;
	private SpriteRenderer wrong;
	private SpriteRenderer plus;
	private SpriteRenderer one;
	private SpriteRenderer three;
	
	private Vector3 redScale; //the original scale of the sprite pBT_3
	private Vector3 greenScale; //the original scale of the sprite pBT_2
	
	private Animator anim;//reference to the animator of TeasingToGrind
	
	private float total;// the total amount of time/fill for the bar ( what is it? 1 or two second? float duh)
	private float tempo;//the timer which measures the current time in deltaTime ( seconds)

	private float addTime;//this thing will add time to the countdown
	private float timeLeft;//this is the countdown
	private float timeMax;//this is the starting value of the countdown
	private bool kaput;//this is for GAME OVER!
	private float lastedFor;//to see how much you lasted
	
	private bool buttonPressed;//bool to refer wether the button has been pressed or not.
	private bool s1g1 = false;//Condition for wether s1g1 should play
	private bool s1g2 = false;//as above, but for s1g2
	
	void Awake (){
		//Set up references!!!
		pBT_3 = GameObject.Find("ProgressBarTest_3").GetComponent<SpriteRenderer>();
		pBT_1 = GameObject.Find("ProgressBarTest_1").GetComponent<SpriteRenderer>();
		pBT_2 = GameObject.Find("ProgressBarTest_2").GetComponent<SpriteRenderer>();
		star = GameObject.Find("Considerations").GetComponent<SpriteRenderer>();
		wrong = GameObject.Find("numerini_1").GetComponent<SpriteRenderer>();
		one = GameObject.Find("numerini_5").GetComponent<SpriteRenderer>();
		three = GameObject.Find("numerini_6").GetComponent<SpriteRenderer>();
		plus = GameObject.Find("numerini_8").GetComponent<SpriteRenderer>();
		
		redScale = pBT_3.transform.localScale; // reference to localScale
		greenScale = pBT_2.transform.localScale;
		
		total = 2f; //this value is almost the same as the actual bar lenght, BUT we should try something better than this
		tempo = 0.0f; //tempo needs to start from zero

		timeMax = 10.0f;//these are how many seconds will last the countdown
		kaput = false;//you have yet to loose
		lastedFor = Time.deltaTime;

		// this will allow us to use the FSM I created for those animations and hopefully influence them
		anim = GameObject.Find("TeasingToGrind Sprite").GetComponent<Animator>();
		
		buttonPressed = false; // you start and the button has yet to be pressed, right?
		
	}
	
	// Use this for initialization
	void Start () {
		
		//Set up initial conditions for the Progress Bar
		pBT_3.enabled=false;
		pBT_2.enabled=false;
		pBT_1.enabled=false;
		
		//Set up the similar initial condition for uhm... the popping stuff/props/things/whatever
		star.enabled=false;
		wrong.enabled=false;
		plus.enabled=false;
		one.enabled=false;
		three.enabled=false;
		//this way only the sprite meant to be the background will be visible

		timeLeft = Mathf.Clamp(timeMax,-1.0f,timeMax);//when you start the game, the countdown is full

		InvokeRepeating("CountDown",1.0f,1.0f);
		
	}
	
	// Update is called once per frame
	void Update () {

		//Let the Countdown begin!
		//CountDown();

		//if it isn't over we must let you play, but if it IS...
		if(kaput == false){
			//We must call the function that fills Progress Bar, and check if you pressed THE button
			if(Input.GetKeyDown("space") & tempo<=total+0.2f){
				buttonPressed = true;
			}
			//Run the function that manages the ProgressBar every frame
			ProgressFill();
		}

		if(kaput == true){
			StartCoroutine(GameOver());
		}
	}

	private IEnumerator GameOver(){
		lastedFor = Time.realtimeSinceStartup;
		print ("you lasted for: "+lastedFor);
		EditorApplication.isPaused = true;
		yield return null;
	}

	void CountDown(){
		//Real game won't be a run against time, but this is NOT the real game so... let's add some thrill!

		if(timeLeft<0.0f){//you should add difficulty parameter here to make it harder if wished
			kaput = true;
			CancelInvoke("CountDown");
		}
		else{
			timeLeft --;
			print ("timeleft: "+timeLeft);
		}
	}

	void ProgressFill(){
		//The function of which consists the minigame
		//first, what the button does
		if(buttonPressed == false){
			tempo += Time.deltaTime * 7.0f;//this way tempo is linked to realtime ( seconds I should say), not frames, it was x4
		}
		else{
			tempo = tempo;
			StartCoroutine(ProgressReset());
		}
		//then, what this function does
		if(tempo!=total){
			pBT_3.enabled=true;
			pBT_3.transform.localScale = new Vector3(Mathf.Clamp(redScale.x * tempo,0.0f,1.0f),1,1);//you should multiply tempo * difficulty to add more challange if desired.
			if(tempo>total/2){
				pBT_2.enabled=true;
				pBT_2.transform.localScale = new Vector3(Mathf.Clamp(greenScale.x * tempo/2,0.0f,1.0f),1,1);//you should multiply tempo * difficulty to add more challange if desired.
			}
			if(tempo>total){
				pBT_1.enabled=true;
			}
		}
		if(tempo>total+0.2f){
			tempo=tempo;
			StartCoroutine(ProgressReset());
		}
		//print ("ProgressFill done");
	}
	private IEnumerator ProgressReset(){
		//We must return to starting values
		//We must also play the right animations dude! We need to do that from here
		Cow ();
		//And let you know if you did something bad... or good, assuming you tried to push THE button!
		if(buttonPressed == true){
			if(tempo<=total/2){
				wrong.enabled=true;
				s1g1=true;
			}
			if(tempo>total/2){
				star.enabled=true;
				plus.enabled=true;
				one.enabled=true;
				s1g2 = true;
				if(tempo>total){
					one.enabled=false;
					three.enabled=true;
					s1g2 = true;
				}
			}
			yield return new WaitForSeconds(0.5f);
			buttonPressed = false;
		}
		else{ //if you haven't pressed THE button you loose anyway!
			wrong.enabled=true;//had to put it here to make it work, crappy programming!
			s1g1=true;
			pBT_1.enabled=false;
			pBT_2.enabled = false;
			pBT_3.enabled = false;
			yield return new WaitForSeconds(0.5f);
		}
		ResetAll();
		//print ("Progress Reset done");
	}

	void ResetAll(){
		//just to be SUPERSURE...
		//trying to implement countdown bonus
		if(one.enabled == true){
			timeLeft += 0.5f;//this was meant for countDown...
		}
		if(three.enabled == true){
			timeLeft += 1.5f;//this was meant for countDown...
		}

		tempo = 0.0f;
		pBT_1.enabled=false;
		pBT_2.enabled = false;
		pBT_3.enabled = false;
		star.enabled=false;
		wrong.enabled=false;
		plus.enabled=false;
		one.enabled=false;
		three.enabled=false;
		s1g2=false;
		anim.SetBool("s1g1",false);
		anim.SetBool("s1g2",false);

		//print ("Reset All done");
	}
	void Cow(){
		//Cow is a function that says Unity what to do next, after you press the button
		// to make it work properly those ifs need multiple conditions but I don't know why, they should be implicit.
		if(s1g1 & tempo<=total/2){
			anim.SetTrigger("s1g1");
		}
		if(s1g2 & tempo>total/2){
			anim.SetTrigger("s1g2");
		}
	}
}

If I have to say what I was doing wrong in the beginning, I’d say that was pretending to manage animations through code… once I wrapped my head around the new features of the Animator I started to comply with the right path, and SetTrigger used properly helped a lot.