StartCoroutine 被调用了很多次(C# Unity)
StartCoroutine is being called so many times (C# Unity)
我正在 Unity 中创建弹出菜单选项。现在我的问题是我在 void update 中创建的协程被调用了很多次。我的意思是在我的 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);
}
不要在 Update
方法中使用 StartCoroutine()
。在另一种方法中调用它,并在需要时在 coroutine
函数中使用 while loop
。只需在 Update
方法
之外控制你的 StartCoroutine()
每帧都会调用更新,如果您的条件为真,则每帧都会启动协程。
只需设置您的标志,仅加入 1 次即可。
void Update()
{
if (startFinding)
{
startFinding = false;
StartCoroutine(GameOptions());
}
}
协程的工作原理如下:
假设我有一个名为 MyRoutine 的协程函数(在你的例子中,你称之为 GameOptions)
private IEnumerator MyRoutine()
然后,在我的代码中的任何位置,调用
StartCoroutine(MyRoutine));
将像任何常用方法一样简单地调用 MyRoutine
。所以如果你在更新中调用它,它会一直被调用,就像任何方法一样。这不是你想要的。协同程序的特别之处在于您可以在其中使用 yield
关键字。有很多使用方法,但最常用(也是最简单)的方法是 yield return null
yield return null
的意思是"Stop this coroutine, but resume the execution on next frame".你不需要调用任何其他函数(当然不是StartCoroutine)。执行将在下一帧恢复。
要回到您在问题中发布的内容,您在最后写了 yield return null
。所以你的方法正在执行,就在最后,停止并恢复下一帧,但由于没有什么可做的,它在下一帧退出。
使用协程的典型方法是让 yield return null
处于 while 循环中,因此当它恢复时,它会继续循环。这是一个例子
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
是您希望在恢复之前等待的时间,以秒为单位
// 编辑结束
我正在 Unity 中创建弹出菜单选项。现在我的问题是我在 void update 中创建的协程被调用了很多次。我的意思是在我的 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);
}
不要在 Update
方法中使用 StartCoroutine()
。在另一种方法中调用它,并在需要时在 coroutine
函数中使用 while loop
。只需在 Update
方法
StartCoroutine()
每帧都会调用更新,如果您的条件为真,则每帧都会启动协程。 只需设置您的标志,仅加入 1 次即可。
void Update()
{
if (startFinding)
{
startFinding = false;
StartCoroutine(GameOptions());
}
}
协程的工作原理如下:
假设我有一个名为 MyRoutine 的协程函数(在你的例子中,你称之为 GameOptions)
private IEnumerator MyRoutine()
然后,在我的代码中的任何位置,调用
StartCoroutine(MyRoutine));
将像任何常用方法一样简单地调用 MyRoutine
。所以如果你在更新中调用它,它会一直被调用,就像任何方法一样。这不是你想要的。协同程序的特别之处在于您可以在其中使用 yield
关键字。有很多使用方法,但最常用(也是最简单)的方法是 yield return null
yield return null
的意思是"Stop this coroutine, but resume the execution on next frame".你不需要调用任何其他函数(当然不是StartCoroutine)。执行将在下一帧恢复。
要回到您在问题中发布的内容,您在最后写了 yield return null
。所以你的方法正在执行,就在最后,停止并恢复下一帧,但由于没有什么可做的,它在下一帧退出。
使用协程的典型方法是让 yield return null
处于 while 循环中,因此当它恢复时,它会继续循环。这是一个例子
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
是您希望在恢复之前等待的时间,以秒为单位
// 编辑结束