Home > other >  Check when multiple coroutines are all done
Check when multiple coroutines are all done

Time:09-27

So I am making a dice rolling game, every turn the game generates between 1 and 3 dice that "roll" with a coroutine.

I am trying to find a way to check when all the dice are done rolling to do something.

My dice code (attached to each dice object created):

public class Dice : MonoBehaviour {

    // Array of dice sides sprites to load from Resources folder
    public Sprite[] diceSides;
    public GameObject DiceObject;
    public int finalSide = 0;
    public bool doneRolling = false;

    // Reference to sprite renderer to change sprites
    private SpriteRenderer rend;

    public  void Awake() {
    suspect = GameObject.Find("suspect");
    }
    // Use this for initialization
    private void Start () {

        // Assign Renderer component
        rend = GetComponent<SpriteRenderer>();

    }
    
    // If you left click over the dice then RollTheDice coroutine is started
    public void Rolling()
    {
        DiceObject.SetActive(true);
        StartCoroutine("RollTheDice");
    }

    // Coroutine that rolls the dice
    private IEnumerator RollTheDice()
    {
        // Variable to contain random dice side number.
        // It needs to be assigned. Let it be 0 initially
        int randomDiceSide = 0;

        // Final side or value that dice reads in the end of coroutine

        // Loop to switch dice sides ramdomly
        // before final side appears. 20 iterations here.
        for (int i = 0; i <= 20; i  )
        {
            // Pick up random value from 0 to 5 (All inclusive)
            randomDiceSide = Random.Range(0, 5);

            // Set sprite to upper face of dice from array according to random value
            this.GetComponent<Image>().sprite = diceSides[randomDiceSide];

            // Pause before next iteration
            yield return new WaitForSeconds(0.05f);
            doneRolling = true;
        }

        // Assigning final side so you can use this value later in your game
        // for player movement for example
        finalSide = randomDiceSide   1;

    }
}

Now what would be the best way to check when all the dice created are done rolling and trigger another script at that time?

I was thinking about creating another game object that would be a parent of all the dice and do something like:

public class diceRollerCheck : MonoBehaviour
{

    public void checkIfDiceAreDoneRolling(){
        allDiceAreDone = false;
        while(allDiceAreDone == false){
            foreach (Transform child in this) {
                if (child.GetComponent<Dice>().doneRolling == false){
                    allDiceAreDone = false;
                }
                else{
                    allDiceAreDone = true;
                }
        }
    }
}

(This obviously doesn't work but that's the idea)

CodePudding user response:

You can create an action or event on Dice.cs that invokes on same time with doneRolling = true;

Then on DiceRollerCheck.cs, you can create a list of dice like List or any data structure that you think is the best. And you can get all dices on Start() method with findobjectsoftype or if you instantiate dices in runtime force Dice.cs to find DiCeRoller.cs and add itselt to list.

and then subscribe every dice.cs doneRolling event with a method you created in Dicerollercheck.cs where you gonna count doneRolling and number of dice elements, and count equal to number of dice you have then it means all dices are donerolling.

CodePudding user response:

I guess you can assign the number of active dice to a static class, then when a dice is done rolling, it assigns itself to that class, when all classes have assigned themselves, a callback is invoked.
Let's assume you have a class where you activate your dice. I call this class DiceActivator.cs, and the aforementioned static class is called Manager.cs:

DiceActivator:

private void Start()
{
    // this line of code must be where you activate your dice.
    Manager.ActiveDice = 3;
    Manager.callback  = DiceDone;
}

private void DiceDone()
{
    print("done");
}

Manager class (which is static):

private static int _doneDice;
public static int ActiveDice { set; get; }

public static Action callback;

public static void Register()
{
    _doneDice  ;

    if (_doneDice != ActiveDice) return;

    _doneDice = 0;
    callback?.Invoke();
}

finally, add this line of code to the last line of RollTheDice method in Dice class:

private IEnumerator RollTheDice()
{
//..
Manager.Register();
}
  • Related