Unity Game Engine でゲームを開発してきましたが、ページ化された地形を無限の世界 (最近では一般的なテーマ) に使用できるようになることを願っています。私の地形ジェネレーターは、パーリン ノイズのみを使用します。しかし、現時点では、バグによって開発が大幅に遅れています。ページの端が一致せず、近くにもありません。問題は、地形を生成するコードのどこか、またはページの生成が完了するたびに実行される別のコードのどこかにある可能性があります。しかし、ユニティ関数の呼び出しに問題があるわけではないので、ユニティに慣れていなくても助けていただけます。
考えられる原因... 1) 各ページの間違った場所でサンプリングされたパーリン ノイズ、数学の失敗。2) 乱数ジェネレーターは、ページの生成の間に再シードされています。3) ページ生成の間にパーリン ノイズが再シードされます。4) ? 知らない。
注: 他のすべてのコードを見て、番号 2 と 3 をほぼ除外しました。私はジェネレーターを 1 回ずつシードするだけで、Unity はジェネレーターの実行の間に Random を再シードすることはありません。
実際、これを簡単にするデバッグの方法を説明できる場合は、アドバイスしてください。長期的には、それは私をはるかに助けるでしょう.
Unity3D を知らなくてもいいように、ページごとに 1 回実行するコードを次に示します。完全なコメントが付いています。
/* 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 スクリプトが添付されています)。そこからパラメーターをパーリン ノイズに変更できます。現在、最初のパーリン オクターブである o_elevator のみが地形生成でアクティブであることに注意してください。このグリッチを解決する目的で、他のすべてのパブリック perlin オクターブ変数は影響を与えません。