Start例程被调用了很多次(C#Unity)
我正在Unity中创建一个弹出菜单选项。现在我的问题是,我在void update中创建的协同程序被调用了很多次。我的意思是,在我的Unity控制台上,Debug.log正在增加。它不应该是正确的,因为它已经协同工作了。可以帮助我了解更多的合作项目,帮助我解决我的小问题吗 这是我的密码:Start例程被调用了很多次(C#Unity),c#,arrays,unity3d,coroutine,C#,Arrays,Unity3d,Coroutine,我正在Unity中创建一个弹出菜单选项。现在我的问题是,我在void update中创建的协同程序被调用了很多次。我的意思是,在我的Unity控制台上,Debug.log正在增加。它不应该是正确的,因为它已经协同工作了。可以帮助我了解更多的合作项目,帮助我解决我的小问题吗 这是我的密码: [SerializeField] GameObject Option; [SerializeField] Button btn,btn2; [SerializeField] GameObject open, c
[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);
}
[序列化字段]
游戏对象选项;
[序列化字段]
按钮btn,btn2;
[序列化字段]
游戏对象打开,关闭;
[序列化字段]
游戏对象[]选择;
bool startFinding=false;
void Start()
{
Option.SetActive(false);
按钮弹出=btn.GetComponent();
按钮popUp2=btn2.GetComponent();
popUp.onClick.AddListener(PopUpOption);
popUp2.onClick.AddListener(ClosePopUp);
}
无效更新()
{
如果(开始查找)
{
start例程(GameOptions());
}
}
IEnumerator游戏选项()
{
//拿到所有的标签
opt=GameObject.FindGameObjectsWithTag(“MobileOptions”);
if(opt[0].GetComponent().isOn==true&&opt[1].GetComponent().isOn==true)
{
Log(“首先禁用该复选框,然后在“+”'rendering'+”和“+”'livestreaming'”之间仅选择1个选项);
}
//直播
if(opt[0].GetComponent().isOn==true)
{
Log(“Livestreaming激活”);
}否则
{
Log(“Livestreaming停用”);
}
//渲染
if(opt[1].GetComponent().isOn==true)
{
Log(“渲染激活”);
}否则
{
Debug.Log(“呈现停用”);
}
//雾
if(opt[2].GetComponent().isOn==true)
{
调试日志(“雾激活”);
}否则
{
Debug.Log(“雾停用”);
}
//摄影机效果
if(opt[3].GetComponent().isOn==true)
{
调试日志(“相机效果激活”);
}否则{
Debug.Log(“相机效果停用”);
}
收益返回空;
}
void PopUpOption()
{
startFinding=true;
//禁用移动选项按钮
open.SetActive(false);
//启用关闭选项按钮
close.SetActive(true);
//激活移动选项
Option.SetActive(true);
}
void ClosePopUp()
{
开始查找=错误;
//单击“移动选项”按钮
open.SetActive(true);
//禁用关闭选项按钮
close.SetActive(false);
//停用移动选项
Option.SetActive(false);
}
不要在更新方法中使用启动例程()
。在另一个方法中调用它,如果需要,在coroutine
函数中使用while循环
。只需在Update
方法之外控制您的start例程()
,不要在Update
方法中使用start例程()
。在另一个方法中调用它,如果需要,在coroutine
函数中使用while循环
。只要控制start例程()
之外的Update
方法每帧调用一次更新,如果您的条件为真,则每帧启动一次协同例程。
只要放下你的旗帜,只加入一次
void Update()
{
if (startFinding)
{
startFinding = false;
StartCoroutine(GameOptions());
}
}
更新在每一帧调用,如果您的条件为真,则在每一帧启动您的协同路由。
只要放下你的旗帜,只加入一次
void Update()
{
if (startFinding)
{
startFinding = false;
StartCoroutine(GameOptions());
}
}
以下是协同程序的工作原理:
假设我有一个名为MyRoutine的couroutine函数(在您的例子中,您称之为GameOptions)
然后,在我的代码中的任何地方,调用
StartCoroutine(MyRoutine));
只需像任何常用方法一样调用MyRoutine
。因此,如果在update中调用它,它将一直被调用,就像任何方法一样。这不是你想要的。协同程序的特殊之处在于,您可以在其中使用yield
关键字。有很多方法可以使用它,但最常用(也是最简单)的一种方法是执行并返回null
yield return null
表示“停止此协同例程,但在下一帧继续执行”。您不需要调用任何其他函数(当然不需要调用start例程)。执行将在下一帧恢复
为了回到你在问题中发布的内容,你在最后写了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()函数中或稍后触发事件时会调用Start例程
如果您想了解有关协同程序的更多信息,或者检查您是否正确理解它们,请查看此页面:
还是这个视频
//编辑:快速呈现一个有用的选项
在上面的代码段中,while循环与Update函数非常相似(循环的内部在每一帧执行)。一个很好的选择是替换
yield return null
借
其中,waitTime
是恢复前要等待的时间,以秒为单位
//编辑结束以下是协同程序的工作方式:
假设我有一个名为MyRoutine的couroutine函数(在您的例子中,您称之为GameOptions)
然后,在我的代码中的任何地方,调用
StartCoroutine(MyRoutine));
只需像任何常用方法一样调用MyRoutine
。因此,如果在update中调用它,它将一直被调用,就像任何方法一样。这不是你想要的。协同程序的特殊之处在于,您可以在其中使用yield
关键字。有很多方法可以使用它,但最常用(也是最简单)的一种方法是执行并返回null
yield return null
表示“停止此协同程序,但在下一帧继续执行”。您不需要