Jelita Purches
Jelita Purches

Reputation: 1

Using coroutines and loops to have a repeatable delay in Unity?

I'm very new to coding and am trying to make a basic simon says game. Currently I have a cube that is supposed to change the material after a few seconds however I'm really struggling getting any sort of timer to loop so that the cube changes materials, pauses, changes materials again.

this is a part of the code I have currently. At the moment, it crashes a lot and I'm fairly certain it's thanks to my while loop messing it up.

   private void Awake()
   {
       while(i < 3)
       {
           StartCoroutine(Delay());
           i++;
       }
       
   }

   private IEnumerator Delay()
   {
       yield return new WaitForSeconds(3);
       ChangeColour();
   }

   void ChangeColour()
   {
       // we want to change simon's colour
       simon.GetComponent<Renderer>().material = callList[i];
       

   }

Upvotes: -1

Views: 48

Answers (1)

derHugo
derHugo

Reputation: 90813

(Despite as mentioned the fact that your code wouldn't compile as it stands.)

What you are currently doing is starting 3 Coroutines at the same time that will basically all wait the same amount of time and then 3 seconds later all change the material "at the same time".

From your code attempts I would assume you are looking for something like e.g.

[SerializeField] Renderer simon;
[SerializeField] Material[] callList;
[SerializeField] float delay = 3f;

// Yes, you can do this and Unity will run this as a Coroutine implicitly
private IEnumerator Start()
{
    var wait = new WaitForSeconds(delay);

    // This will iterate ONCE through the array
    // and change the material in "delay" seconds interval
    foreach(var material in callList)
    // alternatively
    //for(var i = 0; i < callList.Length; i++);
    //{
    //    var material = callList[i];
    {
        yield return wait;

        simon.material = material;
    }
}

Or alternatively if you rather want to infinitely wrap around the materials

[SerializeField] Renderer simon;
[SerializeField] Material[] callList;
[SerializeField] float delay = 3f;

private IEnumerator Start()
{
    var wait = new WaitForSeconds(delay);
    var i = 0;

    // This is fine in an Enumerator as long as you yield somewhere
    while(true)
    {
        yield return wait;

        simon.material = callList[i];

        // increase by one but wrap around at the end of the array
        i = (i + 1) % callList.Length;
    }
}

or alternatively to that as said you can also go without a Coroutine and do e.g.

[SerializeField] Renderer simon;
[SerializeField] Material[] callList;
[SerializeField] float delay = 3f;
int currentIndex;

private void Start()
{
    InvokeRepeating(nameof(ChangeColor), delay, delay);
}

private void ChangeColor()
{
    simon.material = callList[i];

    currentIndex = (currentIndex + 1) % callList.Length;
}

Upvotes: 1

Related Questions