StartCoroutine is being called so many times (C# Unity)

天大地大妈咪最大 提交于 2019-12-02 10:00:02

Here is how coroutines work:

Let's say I have a couroutine function called MyRoutine (in your case, you called it GameOptions)

private IEnumerator MyRoutine()

Then, anywhere in my code, calling

StartCoroutine(MyRoutine));

Is going to simply call MyRoutine like any usual method. So if you call it in update, it will be called all the time, as any method would. This is not what you want. What make coroutines special is that you can use the yield keyword in them. There are many ways to use it but the most used (and simple) one is to do yield return null

yield return null means "Stop this coroutine, but resume the execution on next frame". You don't need to call any other function (certainly not StartCoroutine). The execution will resume next frame.

To go back to what you posted in your question, you wrote yield return null at the end. So your method is executing, and just at the end, stops and resumes next frame, but since there is nothing left to do, it exits on the next frame.

A typical way to use coroutines is to have the yield return null in a while loop, so when it resumes, it continues the loop. Here is an example that do it

private IEnumerator MyRoutine()
{
    while(running) //running is a member bool that you could set to false to exit
    {
        // Do all the stuff you want to do in ONE frame
        // ...
        yield return null;
    }
}

Typically, the StartCoroutine would be called in the Start() function, or later when an event is triggered.

If you want to know more about coroutine, or check that you understood them properly, check out this page: https://docs.unity3d.com/Manual/Coroutines.html

or this video https://unity3d.com/learn/tutorials/topics/scripting/coroutines

// Edit: quickly present one useful option

In the snippet above, the while loop is very similar to the Update function (the inside of the loop is executed each frame). One nice option is to replace

yield return null

by

yield return new WaitForSeconds(waitTime)

where waitTime is a the time you want to wait before resuming, in seconds

// End of edit

Do not use StartCoroutine() in the Update method. Call it in another method and use a while loop inside your coroutine function if needed. Just control your StartCoroutine() outside of Update method

Update is called every frame, if your condition is ever true, you launch your coroutine every frame. Just set down your flag to only join 1 time.

void Update()
{
    if (startFinding)
    {
        startFinding = false;
        StartCoroutine(GameOptions());
    } 
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!