StartCoroutine被调用了很多次(C#Unity)

时间:2018-01-11 04:33:18

标签: c# arrays unity3d coroutine

我在Unity中创建弹出菜单选项。现在我的问题是我在无效更新中做的协程被调用了很多次。我的意思是在我的Unity控制台上,Debug.Logs正在递增。它应该是正确的,因为它已经是协程。有些人可以帮我理解更多的协程并帮助我解决我的小问题。

这是我的代码:

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

3 个答案:

答案 0 :(得分:1)

请勿在{{1​​}}方法中使用StartCoroutine()。如果需要,可以使用其他方法调用它,并在Update函数中使用while loop。只需控制coroutine方法之外的StartCoroutine()

即可

答案 1 :(得分:1)

以下是协同程序的工作原理:

让我们说我有一个名为MyRoutine的couroutine函数(在你的情况下,你称之为GameOptions)

private IEnumerator MyRoutine()

然后,在我的代码中的任何地方,调用

StartCoroutine(MyRoutine));

只需像任何常用方法一样调用MyRoutine。因此,如果你在更新中调用它,它将一直被调用,就像任何方法一样。这不是你想要的。协同程序的特殊之处在于您可以在其中使用 yield 关键字。有很多方法可以使用它,但最常用(和简单)的方法是 yield return null

yield return null表示&#34;停止此协程,但在下一帧恢复执行&#34;。您不需要调用任何其他功能(当然不是StartCoroutine)。执行将在下一帧恢复。

要回到您在问题中发布的内容,最后写了yield return null。所以你的方法正在执行,最后,停止并恢复下一帧,但由于没有什么可做的,它会在下一帧退出。

使用协同程序的一种典型方法是在while循环中使用yield return null,因此当它恢复时,它会继续循环。这是一个做它的例子

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()函数中调用,或者稍后在触发事件时调用。

如果您想了解有关协程的更多信息,或检查您是否正确理解它们,请查看此页:https://docs.unity3d.com/Manual/Coroutines.html

或此视频https://unity3d.com/learn/tutorials/topics/scripting/coroutines

//编辑:快速提供一个有用的选项

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

yield return null

通过

yield return new WaitForSeconds(waitTime)

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

//编辑结束

答案 2 :(得分:0)

每帧调用更新,如果你的条件是真的,你每帧都会启动你的协同程序。 只需将你的旗帜设置为加入1次即可。

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