最新消息:Welcome to the puzzle paradise for programmers! Here, a well-designed puzzle awaits you. From code logic puzzles to algorithmic challenges, each level is closely centered on the programmer's expertise and skills. Whether you're a novice programmer or an experienced tech guru, you'll find your own challenges on this site. In the process of solving puzzles, you can not only exercise your thinking skills, but also deepen your understanding and application of programming knowledge. Come to start this puzzle journey full of wisdom and challenges, with many programmers to compete with each other and show your programming wisdom! Translated with DeepL.com (free version)

c# - Using coroutines and loops to have a repeatable delay in Unity? - Stack Overflow

matteradmin7PV0评论

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];
       

   }

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];
       

   }
Share Improve this question edited Nov 17, 2024 at 19:01 derHugo 91.4k9 gold badges91 silver badges135 bronze badges asked Nov 17, 2024 at 6:42 Jelita PurchesJelita Purches 11 silver badge 4
  • 3 first, you need to show the actual errors. "Crashes a lot" is not good enough. Second, i in callList[i] is undefined – Felix Commented Nov 17, 2024 at 6:46
  • so, why are you starting the delay a number of times? it doesnt pass "i" into it, they will also run at roughly the same time because all 3 start at say 0 seconds and 3 seconds later all 3 will run. You almost certainly wanted a for i is 0 to < callList.Length do wait 3 seconds, set material loop. in your coroutine.. and delay would then be a bad name for it. – BugFinder Commented Nov 17, 2024 at 12:00
  • I guess the loop should rather go into your coroutine instead .. or rather directly go with InvokeRepeating instead – derHugo Commented Nov 17, 2024 at 18:51
  • It looks like you're pretty new to StackOverflow. Welcome! This question is probably close to being answerable but needs some help. Please read stackoverflow/help/how-to-ask and edit your question to make it so people can help you better. – Adam B Commented Nov 18, 2024 at 4:33
Add a comment  | 

1 Answer 1

Reset to default 1

(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;
}
Post a comment

comment list (0)

  1. No comments so far