StartCoroutine被调用了很多次(C#Unity) [英] StartCoroutine is being called so many times (C# Unity)

查看:1046
本文介绍了StartCoroutine被调用了很多次(C#Unity)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在Unity中创建一个弹出菜单选项.现在我的问题是我在void更新中制作的协程被调用了很多次.我的意思是,在我的Unity Console上,Debug.Logs正在递增.它不应该正确,因为它已经协程了.可以帮助我了解更多的协程并帮助我解决我的小问题.

I'm creating a Pop up menu Option in Unity. Now my Problem here is that the coroutine i made in void update is being called so many times. What i mean by that is on my Unity Console the Debug.Logs are incrementing . It should not right because its already coroutine. Could some help me understand more coroutine and help me solve my little problem .

这是我的代码:

[SerializeField]
GameObject Option;
[SerializeField]
Button btn,btn2;
[SerializeField]
GameObject open, close;

[SerializeField]
GameObject[] opt;
bool startFinding = false;
void Start()
{
    Option.SetActive(false);
    Button popUp = btn.GetComponent<Button>();
    Button popUp2 = btn2.GetComponent<Button>();
    popUp.onClick.AddListener(PopUpOption);
    popUp2.onClick.AddListener(ClosePopUp);


}

void Update()
{
    if (startFinding)
    {
        StartCoroutine(GameOptions());
    } 
}

IEnumerator GameOptions()
{

    //Get All the tags
    opt = GameObject.FindGameObjectsWithTag("MobileOptions");

    if (opt[0].GetComponent<Toggle>().isOn == true && opt[1].GetComponent<Toggle>().isOn == true)
    {
        Debug.Log("Disable first the check box then choose only 1 option between" + "'rendering'"+ "and" + "'livestreaming'");
    }
    //Livestreaming
    if (opt[0].GetComponent<Toggle>().isOn == true)
    {
        Debug.Log("Livestreaming Activate");
    } else 
    {
        Debug.Log("Livestreaming Deactivate");
    }
    //Rendering
    if (opt[1].GetComponent<Toggle>().isOn == true)
    {
        Debug.Log("Rendering Activate");
    } else
    {
        Debug.Log("Rendering Deactivate");
    }
    //Fog

    if (opt[2].GetComponent<Toggle>().isOn == true)
    {
        Debug.Log("Fog Activated");
    } else
    {
        Debug.Log("Fog Deactivated");
    }

    //Camera Effect
    if (opt[3].GetComponent<Toggle>().isOn == true)
    {
        Debug.Log("Camera Effect Activated");
    } else {
        Debug.Log("Camera Effect Deactivated");
    }
        yield return null;
}

void PopUpOption()
{
    startFinding = true;
    //Disable The Mobile Option Button
    open.SetActive(false);
    //Enable the Close Option Button
    close.SetActive(true);
    //activate the Mobile Options
    Option.SetActive(true);

}

void ClosePopUp()
{
    startFinding = false;
    //eanble the mobile option button
    open.SetActive(true);
    //disable the close option button
    close.SetActive(false);
    //deactivate the Mobile Option
    Option.SetActive(false);
}

推荐答案

以下是协程的工作方式:

假设我有一个名为MyRoutine的Couroutine函数(在您的情况下,您将其称为GameOptions)

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

将像通常的方法一样简单地调用MyRoutine.因此,如果您在更新中调用它,那么它将始终被调用,就像任何方法一样.这不是您想要的.协程之所以与众不同,是因为您可以在其中使用 yield 关键字.有很多使用方法,但是最常用(也是最简单)的方法是 yield return null

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的意思是停止此协程,但在下一帧继续执行".您不需要调用任何其他函数(当然不是StartCoroutine).执行将在下一帧继续.

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.

要返回您在问题中发布的内容,您在末尾写了yield return null.因此,您的方法正在执行,并在最后一刻停止并继续下一帧,但是由于没有其他事情要做,因此它将在下一帧退出.

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.

使用协程的一种典型方法是将yield return null置于while循环中,因此当它恢复时,它将继续循环.这是一个做到这一点的例子

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

通常,StartCoroutine将在Start()函数中调用,或者稍后在触发事件时调用.

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

或此视频 https://unity3d.com/learn/tutorials/topics/脚本/协程

//快速显示一个有用的选项

在上面的代码段中,while循环与Update函数非常相似(循环内部每帧执行一次).一个不错的选择是替换

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

通过

yield return new WaitForSeconds(waitTime)

其中waitTime是您要等待的恢复时间,以秒为单位

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

//编辑结束

这篇关于StartCoroutine被调用了很多次(C#Unity)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆