如何防止我的代码产生每一帧?
How can I prevent my code from yielding every frame?
我正在调用一种方法,该方法会调用自身来爬过地形并创建区域。然而,当区域变大时,该过程以堆栈溢出结束。通过强制代码让步并花时间它成功完成并爬行我地图中的 3 个区域。然而,我使用的方法是产生每一帧,我不知道如何让它每 100 帧产生一次,导致它完成速度非常慢。这是我为提高可读性所做的伪代码:
public int timer = 0;
void Awake(){
StartCoroutine(crA);
}
public IEnumerator crA(){
//stuff
yield return StartCoroutine(crB());
//stuff that needs to happen only after crB finishes
}
public IEnumerator crB(){
timer = 0;
yield return StartCoroutine(crC());
}
public IEnumerator crC(){
//Crawiling code, crawls terrain to create a zone
if(x){ yield break;}
timer++;
//vv I WANTED IT TO YIELD ONLY IN HERE
if (timer ==100){
timer = 0;
yield return null;
}
//^^
yield return StartCoroutine(crC());
yield return StartCoroutine(crC());
yield return StartCoroutine(crC());
yield return StartCoroutine(crC());
yield return StartCoroutine(crC());
}
似乎 yield return startcoroutine 导致了 yield,但我不知道该用什么代替。任何帮助将不胜感激。
一般来说只要你使用yield
它至少会yield
一帧像
yield return null;
会。
您可以做的是“手动”使用 IEnumerator.MoveNext
而不放弃它。如果您使用 StartCoroutine
.
,这基本上就是 Unity 协程每帧调用一次的内容
然后只有在你想这样做的时候才屈服。给定您的伪代码,例如
private void Awake()
{
StartCoroutine(crA);
}
public IEnumerator crA()
{
//stuff
yield return crB();
//stuff that needs to happen only after crB finishes
}
public IEnumerator crB()
{
timer = 0;
// "Manually" run the routine instead of using Unity Coroutine interface
var crc = crC();
while(crc.MoveNext())
{
if(timer >= 100)
{
yield return null;
timer = 0;
}
}
}
public IEnumerator crC()
{
//Crawiling code, crawls terrain to create a zone
if(x) yield break;
timer++;
yield return crC();
yield return crC();
yield return crC();
yield return crC();
yield return crC();
}
然后如前所述,您可以基于时间而不是使用 frame/call 计数器而不是使用例如一个 StopWatch
private const float TARGET_FRAMERATE = 60;
public IEnumerator crB()
{
var targetMilliseconds = 1000f / TARGET_FRAMERATE;
var sw = new StopWatch();
sw.Start();
// "Manually" run the routine instead of using Unity Coroutine interface
var crc = crC();
while(crc.MoveNext())
{
if(sw.ElapsedMilliseconds >= targetMilliseconds)
{
yield return null;
sw.Restart();
}
}
}
所以只要最后一次执行超过目标帧率,它就会产生一帧。您必须对值进行一些调整。根据您的用例,30 甚至 24 可能已经足够了。
它基本上是帧速率和实际实时持续时间之间的权衡。
注意:在智能手机上打字,但我希望思路清晰
我正在调用一种方法,该方法会调用自身来爬过地形并创建区域。然而,当区域变大时,该过程以堆栈溢出结束。通过强制代码让步并花时间它成功完成并爬行我地图中的 3 个区域。然而,我使用的方法是产生每一帧,我不知道如何让它每 100 帧产生一次,导致它完成速度非常慢。这是我为提高可读性所做的伪代码:
public int timer = 0;
void Awake(){
StartCoroutine(crA);
}
public IEnumerator crA(){
//stuff
yield return StartCoroutine(crB());
//stuff that needs to happen only after crB finishes
}
public IEnumerator crB(){
timer = 0;
yield return StartCoroutine(crC());
}
public IEnumerator crC(){
//Crawiling code, crawls terrain to create a zone
if(x){ yield break;}
timer++;
//vv I WANTED IT TO YIELD ONLY IN HERE
if (timer ==100){
timer = 0;
yield return null;
}
//^^
yield return StartCoroutine(crC());
yield return StartCoroutine(crC());
yield return StartCoroutine(crC());
yield return StartCoroutine(crC());
yield return StartCoroutine(crC());
}
似乎 yield return startcoroutine 导致了 yield,但我不知道该用什么代替。任何帮助将不胜感激。
一般来说只要你使用yield
它至少会yield
一帧像
yield return null;
会。
您可以做的是“手动”使用 IEnumerator.MoveNext
而不放弃它。如果您使用 StartCoroutine
.
然后只有在你想这样做的时候才屈服。给定您的伪代码,例如
private void Awake()
{
StartCoroutine(crA);
}
public IEnumerator crA()
{
//stuff
yield return crB();
//stuff that needs to happen only after crB finishes
}
public IEnumerator crB()
{
timer = 0;
// "Manually" run the routine instead of using Unity Coroutine interface
var crc = crC();
while(crc.MoveNext())
{
if(timer >= 100)
{
yield return null;
timer = 0;
}
}
}
public IEnumerator crC()
{
//Crawiling code, crawls terrain to create a zone
if(x) yield break;
timer++;
yield return crC();
yield return crC();
yield return crC();
yield return crC();
yield return crC();
}
然后如前所述,您可以基于时间而不是使用 frame/call 计数器而不是使用例如一个 StopWatch
private const float TARGET_FRAMERATE = 60;
public IEnumerator crB()
{
var targetMilliseconds = 1000f / TARGET_FRAMERATE;
var sw = new StopWatch();
sw.Start();
// "Manually" run the routine instead of using Unity Coroutine interface
var crc = crC();
while(crc.MoveNext())
{
if(sw.ElapsedMilliseconds >= targetMilliseconds)
{
yield return null;
sw.Restart();
}
}
}
所以只要最后一次执行超过目标帧率,它就会产生一帧。您必须对值进行一些调整。根据您的用例,30 甚至 24 可能已经足够了。
它基本上是帧速率和实际实时持续时间之间的权衡。
注意:在智能手机上打字,但我希望思路清晰