簡體   English   中英

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

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

我在Unity中創建一個彈出菜單選項。 現在我的問題是我在void更新中制作的協程被調用了很多次。 我的意思是,在我的Unity Console上,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);
}

不要在Update方法中使用StartCoroutine() 在另一種方法中調用它,並在需要的while loopcoroutine函數內部使用while loop 只需在Update方法之外控制StartCoroutine()

這是協程的工作方式:

假設我有一個名為MyRoutine的Couroutine函數(在您的情況下,您將其稱為GameOptions)

private IEnumerator MyRoutine()

然后,在我代碼的任何地方,調用

StartCoroutine(MyRoutine));

將像通常的方法一樣簡單地調用MyRoutine 因此,如果您在update中調用它,它將像任何方法一樣一直被調用。 這不是您想要的。 使協程與眾不同的是,您可以在協程中使用yield關鍵字。 有很多方法可以使用它,但是最常用的(也是最簡單的)一種方法是讓yield return null

yield return null表示“停止此協程,但在下一幀繼續執行”。 您不需要調用任何其他函數(不一定是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;
    }
}

通常,將在Start()函數中或稍后在觸發事件時調用StartCoroutine。

如果您想了解更多有關協程的信息,或者檢查您是否正確理解協程,請查看此頁面: 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是您要在恢復之前等待的時間(以秒為單位)

//編輯結束

更新稱為每幀,如果您的條件為真,則在每幀啟動協程。 只需設置您的標志即可加入1次。

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM