我在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);
}
答案 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());
}
}