如何强制递归函数产生跳帧?

时间:2017-02-14 18:54:09

标签: .net recursion unity3d unityscript yield

如何强制递归函数在运行时产生帧?

我试图在递归函数的不同阶段放置yield函数。

我不明白发生了什么,因为忽略每1000次递归打印时间的if条件,它只产生并打印大约每100万次递归。应该拾取的90%的打印命令将被代码忽略,不会出现。 运行时每1-2分钟只生成一次,并且一次打印十几个语句。

这是我设法编写的最快的代码版本;如果我向上或向下更改yield语句,运行时有时会完全冻结,并且10分钟内不会发生任何事情。

为什么会冻结,我该如何更改?

//A working 3D floodfill function that reads and writes a boolean voxel array: 

private var maxAbort = 1000000000;

function boundary( x:int, y:int, z:int ): IEnumerator //floodfill algo  
{
    if ( read3DboolArray(x,y,z)==false && bcnt<maxAbort){//pprevent stackoverflow with limit FASTER
        if ( x >= 0 && x < bsizex && y >= 0 && y < bsizey && z >= 0 && z < bsizez)
        {           

            write3DboolArray(x,y,z,true);


            boundary(x+1,y,z);
            boundary(x-1,y,z);      yield WaitForFixedUpdate(); 
            boundary(x,y+1,z);
            boundary(x,y-1,z); // yield WaitForFixedUpdate();   
            boundary(x,y,z+1);
            boundary(x,y,z-1);
        }

        if ( bcnt % 1000== 0 )//mark new start if ended this recursion run
        {
            print(bcnt+ "   ------     " +
                (Time.realtimeSinceStartup-tt));
            bcnt+=1;

            yield WaitForFixedUpdate(); 
        }
    } else return; 
}

它正在使用Unity3D的MonoDevelop运行时,它是.NET framework 2.0的一个分支

1 个答案:

答案 0 :(得分:2)

在方法中使用yield本质上将方法转换为迭代器的构造函数。为了让迭代器实际上做一些有意义的事情,你实际上需要迭代它。

    boundary(x+1,y,z);
    boundary(x-1,y,z);      yield WaitForFixedUpdate(); 
    boundary(x,y+1,z);
    boundary(x,y-1,z); // yield WaitForFixedUpdate();   
    boundary(x,y,z+1);
    boundary(x,y,z-1);

这基本上只会创建几个枚举器,然后将它们抛弃。要使递归收益工作,您必须将所有结果一直返回到初始呼叫站点。

使用Yield和Coroutines为这种工作负载执行此操作似乎非常低效。我建议要么尝试将算法重新构建为迭代(by using a stack for example,这也有助于解决明显的堆栈溢出问题),或者将其卸载到单独的工作线程中。