我正在建造一个由数千个星系统组成的太空游戏。现在,有一个功能可以生成数千个系统。生成大约需要5-10秒,我希望有一个简单的进度条来更新进度中的用户。
经过一番搜索,我决定使用一个协程,但是有一点问题:当我调用函数生成星系统时,调用函数的代码继续运行,报告零星(因为它们没有'已经生成了。)
我有一种感觉,coroutines不适合我。基本上,我只是在寻找一种模拟Application.DoEvents来更新GUI的方法。
以下是我的代码示例:
// Start generating thousands of systems
StartCoroutine(GalacticMap.GenerateRandomGalaxy());
// after the universe is generated...
Game.myGalaxy.StarSystems = GalacticMap.myGalaxy.StarSystems;
// report back the number of systems
print(String.Format("Generated {0} systems", Game.myGalaxy.StarSystems.Count));
然而,GalacticMap.GenerateRandomGalaxy()
我正在回归yield return new WaitForSeconds(0.1f);
,效果不是我想要的:当生成仍然在时,执行会直到print
语句去。
那我该怎么做?
我已经编写了一个示例代码来说明我的问题。
来电者代码:
Debug.Log ("Start generating");
StartCoroutine(GenerateMeGalaxy());
Debug.Log ("Finish generating");
我打电话给的代码:
public static IEnumerator GenerateMeGalaxy ()
{
Debug.Log ("GenerateMeGalaxy start");
int numberOfStars = 1000;
for (int i=0;i<=numberOfStars;i++)
{
// generate galaxy
// display progress bar on screen
Debug.Monitor(String.Format("{0}% completed", ((i*100)/numberOfStars)),2);
yield return new WaitForSeconds(0.001f);
}
Debug.Log ("GenerateMeGalaxy end");
}
在上面的代码中,Debug.Log
在屏幕上显示一个新行上的字符串,以便您可以读取以前记录的任何字符串。这是为了调试代码执行。 Debug.Monitor
在屏幕上有一个固定的位置,将覆盖以前的字符串。这是我显示进度百分比的地方。运行此代码后我看到的是:
Start generating
GenerateMeGalaxy start
Finish generating
GenerateMeGalaxy end
我想看到的是:
Start generating
GenerateMeGalaxy start
GenerateMeGalaxy end
Finish generating
...而且进度更新发生在两者之间:
GenerateMeGalaxy start
Finish generating
答案 0 :(得分:0)
我认为你误解了Unity协同程序的工作方式。 yield return new WaitForSeconds(0.1f)
基本上说的是&#34;去做其他事情并在0.1秒之后再回到我身边#34;所以Unity自然会继续做其他事情,包括print语句。
您想要的是以下模式:
IEnumerator GenerateRandomGalaxy()
{
int numSystems = 5000; // however many systems you want to generate
foreach(int i = 0; i < numSystems; i++)
{
// insert code here that generates system i
// insert code here that updates the progress bar
yield return null;
}
// put logic that prints out final number of systems generated here
}
这样做是生成一个系统,更新状态栏,然后 - 使用yield return null
语句 - 告诉Unity接管(以便它做其他事情,包括渲染更新的进度条)然后回来继续循环。
最后,print语句仅在循环结束后才会发生,如您所愿。