我一直在 Unity 游戏引擎中开发一款游戏,我希望能够将分页地形用于无限世界(当今的常见主题)。我的地形生成器专门使用柏林噪声。但是此时,开发已经被一个错误严重拖慢:页面边缘不匹配,甚至不匹配。问题出在我生成地形的代码中,或者可能在每次我完成生成页面时运行的另一段代码中。但是问题绝对不在unity函数调用上,所以即使你不熟悉unity也可以帮助我。
可能的原因... 1) 为每个页面的错误位置采样 Perlin 噪声,数学失败。2) 随机数生成器在页面生成之间重新播种。3) 在页面生成之间重新植入 Perlin 噪声。4) ? 我不知道。
注意:我几乎排除了数字 2 和 3,查看所有其他代码。我每个只为生成器播种一次,Unity 不会碰巧在生成器运行之间重新播种 Random。
实际上,如果您可以描述一种使这更容易的调试方式,请提供建议。从长远来看,这对我有更大的帮助。
这是我为每个页面运行一次的代码,带有完整的注释,因此您不必了解 Unity3D ...
/* x and y are the indices of the tile being loaded. The game maintains a
square of pages loaded, where the number of pages per side is equal to
loadSquares (see below). x and y are the indices of the page to generate
within that square. */
public void generate(int x, int y)
{
/* pagePos represents the world x and y coordinates of the bottom left
corner of the page being generated. This is given by...
new Vector2((-(float)loadSquares / 2.0f + x + xCoord) * tileSize,
(-(float)loadSquares / 2.0f + y + zCoord) * tileSize);
This is because the origin tile's center is at 0, 0. xCoord represents
the tile that the target object is on, which is what the loaded square
is centered around. tileSize is the length of each side of each tile.
*/
Vector2 pagePos = getPagePos(x, y);
//Here I get the number of samples x and y in the heightmap.
int xlim = td[x,y].heightmapWidth;
int ylim = td[x,y].heightmapHeight;
//The actual data
float[,] array = new float[xlim, ylim];
//These will represent the minimum and maximum values in this tile.
//I will need them to convert the data to something unity can use.
float min = 0.0f;
float max = 0.0f;
for(int cx = 0; cx < xlim; cx++)
{
for(int cy = 0; cy < ylim; cy++)
{
//Here I actually sample the perlin function.
//Right now it doesn't look like terrain (intentionally, testing).
array[cx,cy] = sample(
new Vector3((float)cx / (float)(xlim - 1) * tileSize + pagePos.x,
(float)cy / (float)(ylim - 1) * tileSize + pagePos.y,
122.79f));
//On the first iteration, set min and max
if(cx == 0 && cy == 0)
{
min = array[cx,cy];
max = min;
}
else
{
//update min and max
min = Mathf.Min(min, array[cx,cy]);
max = Mathf.Max(max, array[cx,cy]);
}
}
}
//Set up the Terrain object to receive the data
float diff = max != min ? max - min : 10.0f;
tr[x,y].position = new Vector3(pagePos.x, min, pagePos.y);
td[x,y].size = new Vector3(tileSize, diff, tileSize);
//Convert the data to fit in the Terrain object
/* Unity's terrain only accepts values between 0.0f and 1.0f. Therefore,
I shift the terrain vertically in the code above, and I
squish the data to fit below.
*/
for(int cx = 0; cx < xlim; cx++)
{
for(int cy = 0; cy < ylim; cy++)
{
array[cx,cy] -= min;
array[cx,cy] /= diff;
}
}
//Set the data in the Terrain object
td[x,y].SetHeights(0, 0, array);
}
}
有趣且可能很重要的细节:瓷砖与 x/z 方向上相邻角落的瓷砖正确连接。只要瓷砖没有相同的 x-to-z 增量,就会发生采样偏移。在下图中,右侧图块是另一个图块的 +x 和 +z。具有这种关系的所有图块都已正确连接。
这是以 zip 格式上传的项目文件。告诉我它是否不起作用或什么... http://www.filefactory.com/file/4fc75xtd3yzl/n/FPS_zip
要查看地形,如果它没有从那里开始,请在切换到 testScene 后按 Play。GameObject 生成数据和地形对象(它具有来自 scripts/General/ 附加的 RandomTerrain 脚本)。您可以从那里将参数修改为柏林噪声。请注意,现在只有第一个 perlin 八度音程 o_elevator 在地形生成中处于活动状态。为了解决这个故障,所有其他公共 perlin 倍频程变量都没有影响。