我正在为柏林噪声实验制作降水图,在那里我还创建了生物群落。
我正在使用温度和降水来确定某个像素的生物群落,我有降水的程序,但是程序中的多个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)
这足以在您x
和y
后立即检查一次,并且在嵌套循环中不必要地在下面进一步完成 - 如果条件为假,您可以完全跳过这些循环。
实际上,您可以将整个方法移动到线程并使用异步等待结果(另请参阅在 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
}
注意:在智能手机上输入,但我希望这个想法变得清晰