降水地图的嵌入式 For 循环,Unity3d 游戏引擎中存在柏林噪声问题



我正在为柏林噪声实验制作降水图,在那里我还创建了生物群落。

我正在使用温度和降水来确定某个像素的生物群落,我有降水的程序,但是程序中的多个For loops使Unity3d长时间无响应。

有谁知道如何使它更快?我在互联网上四处寻找,但找不到答案

这是我的代码:

public float[,] PrecipMap (float[,] noise,int mapWidth,int mapHeight)
{
float[,] precipMap = new float[mapWidth, mapHeight];//array that it to be used for precipitation
float[,] waterTiles = WaterTiles(mapHeight, mapWidth, noise);//array with all values that are water
for (int y = 0; y < mapHeight; y++)
{
for(int x = 0; x < mapWidth; x++)
{
float[] distance = new float[count];//distance between pixel and water tile
for(int wy = 0; wy < mapHeight; wy++)
{
for(int wx = 0; wx < mapWidth; wx++)
{
if (waterTiles[x, y] == 1) { // if the selected tile in water tiles has water
for(int i = 0; i < count; i++)// distance makes an array of all possible distances. 
{
distance[i] = Mathf.Sqrt(((x + -wx) * (x + -wx)) + ((y +-wy) * (y +-wy)));// finds distance between pixel and water tile 
} 
}
}
Array.Sort(distance); /// sorts distance from least to greatest
precipMap[x, y] = distance[count-1];//enters in distance
}
}
}
return precipMap;
}

如果有人能帮忙,我将不胜感激。我非常感谢任何帮助/批评。

正如已经评论的那样,您的循环运行得非常频繁,默认情况下,unity中的所有内容都在主线程上运行。因此,在 Unity 渲染下一帧之前,您的方法必须完成。

此外,您运行Array.Sort这是非常昂贵的,并为每次迭代分配新数组,这也使您的GC保持忙碌!

那我看不出你的distance数组有什么用。变量i是 Neve 用于 yoir 计算的,因此您只需用相同的值填充所有 1500 个条目,对其进行排序并读出最后一个......无论如何,它们都是平等的,所以这完全是多余的!

你也冗余地检查

if (waterTiles[x, y] == 1)

这足以在您xy后立即检查一次,并且在嵌套循环中不必要地在下面进一步完成 - 如果条件为假,您可以完全跳过这些循环。

实际上,您可以将整个方法移动到线程并使用异步等待结果(另请参阅在 Unity3D 中使用异步等待(。不幸的是,我不是async-await专家,但这应该可以做到

public async void CalculatePrecipMap(float[,] noise, int mapWidth, int mapHeight, Action<float[,]> callback)
{
var result = await PrecipMap(noise, mapWidth, mapHeight);
callback?.Invoke(result);
}
private async Task<float[,]> PrecipMap (float[,] noise,int mapWidth,int mapHeight)
{
//array that it to be used for precipitation
float[,] precipMap = new float[mapWidth, mapHeight];
//array with all values that are water
float[,] waterTiles = WaterTiles(mapHeight, mapWidth, noise);
for (var y = 0; y < mapHeight; y++)
{
for(var x = 0; x < mapWidth; x++)
{   
// Skip as soon as possible
// Completely unnecessary to run your loop at all if this is already false
if (waterTiles[x, y] != 1) continue; 
// if the selected tile in water tiles has water
for(var wy = 0; wy < mapHeight; wy++)
{
for(var wx = 0; wx < mapWidth; wx++)
{
// i is nowhere used in below calculation!
// I don't see any reason to use an distance array here at all !!!                      
precipMap[x, y] = Mathf.Sqrt(((x + -wx) * (x + -wx)) + ((y +-wy) * (y +-wy)));
}
}
}
}
return precipMap;
}

然后,您将使用lambda表达式使用它,例如

CalculatePrecipMap(someNoise, someWidth, someHeight, result =>
{
// Do something with the result
}

或使用类似

CalculatePrecipMap(someNoise, someWidth, someHeight, OnResultReady);
private void OnResultReady (float[,] result)
{
// Do something with the result
}

注意:在智能手机上输入,但我希望这个想法变得清晰

最新更新