【Unity3D】自動生成ダンジョンの処理負荷軽減とマテリアル設定の自動化
どうも、だらはです。
先日は、こちらの記事にて自動生成ダンジョンの作り方を紹介しました。
今回は、処理負荷軽減とマテリアル設定の自動化を実施していきます。
①処理負荷軽減
先ずは、処理負荷軽減についての詳細です。
先回のスクリプトでは、ダンジョンの壁は立方体(Cube)を自動生成して積み上げる仕様でした。
この仕様だと、壁が高くなるにつれて結構な処理負荷増となってしまいます。
対策として、立方体を積み上げるのではなく直方体を1つ配置することにします。
②マテリアル設定の自動化
①により立方体を直方体にすることで、表面のテクスチャが間延びしてしまいます。
これを防止するために、壁の高さに応じてテクスチャのサイズを変更する処理を加えます。
スクリプト
以上の変更内容を反映したのが今回のスクリプトです。
ベースは前回の記事のものを使用して頂き、GenerateWall()を変更します。
◆ElementGenerator.cs
//壁を生成
void GenerateWall()
{
//ダンジョンマップ
dungeonGenerator = GetComponent<DungeonGenerator>();
//壁の高さ
float blockHeight = UnityEngine.Random.Range(4, 100f);
//2Dマップ生成
map = dungeonGenerator.Generate();
//生成する壁の親となるGameObject
GameObject objWall = GameObject.Find("Wall");
GameObject objFloor = GameObject.Find("Floor");
GameObject objCeiling = GameObject.Find("Ceiling");
//マテリアルをランダム選択(materialからmatAssetsに変更)
int matWallIdx = UnityEngine.Random.Range(0, matAssets.Length);
int matFloorIdx = UnityEngine.Random.Range(0, matAssets.Length);
//マテリアルは壁と床で競合する
Material matWall = Instantiate(matAssets[matWallIdx]);
Material matCeiling = Instantiate(matAssets[matWallIdx]);
Material matFloor = Instantiate(matAssets[matFloorIdx]);
//マテリアルのスケール調整
matWall.mainTextureScale = new Vector2(1, blockHeight);
matCeiling.mainTextureScale = new Vector2(50f, 50f);
matFloor.mainTextureScale = new Vector2(50f, 50f);
//足場、天井用
objFloor.GetComponent<Renderer>().material = matFloor;
objCeiling.GetComponent<Renderer>().material = matCeiling;
//天井の高さを変更
Vector3 pos = objCeiling.transform.position;
pos.y = blockHeight;
objCeiling.transform.position = pos;
//自動生成したマップにCubeを配置
for (int i = 0; i < map.GetLength(0); i++)
{
for (int j = 0; j < map.GetLength(1); j++)
{
//壁をCubeで作成
if (map[i, j] == 0)
{
/* ダンジョンの高さ分Cubeを積み上げると処理負荷が厳しいため不採用
for (int k = 0; k < blockHeight; k++)
{
GameObject cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
//Wall直下に階層を移動
cube.transform.parent = objWall.transform;
cube.GetComponent<Renderer>().material = materialWall;
cube.transform.localScale = new Vector3(1, 1, 1);
cube.transform.position = new Vector3(i, k + 0.5f, j);
}
*/
//CubeとMaterialにダンジョンの高さを考慮させる。
GameObject cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
//Wall直下に階層を移動
cube.transform.parent = objWall.transform;
cube.GetComponent<Renderer>().material = matWall;
cube.transform.localScale = new Vector3(1, blockHeight, 1);
cube.transform.position = new Vector3(i, blockHeight/2f, j);
}
else if ((map[i, j] == 1) || (map[i, j] == 2))
{
/* 動的に足場を生成すると処理負荷が厳しいため不採用
GameObject planeL = GameObject.CreatePrimitive(PrimitiveType.Plane);
//Floor直下に階層を移動
planeL.transform.parent = objFloor.transform;
planeL.GetComponent<Renderer>().material = materialFloor;
planeL.transform.localScale = new Vector3(0.1f, 1, 0.1f);
planeL.transform.position = new Vector3(i, 0, j);
GameObject planeH = GameObject.CreatePrimitive(PrimitiveType.Plane);
//Ceiling直下に階層を移動
planeH.transform.parent = objCeiling.transform;
planeH.GetComponent<Renderer>().material = materialFloor;
planeH.transform.localScale = new Vector3(0.1f, 1, 0.1f);
planeH.transform.rotation = Quaternion.Euler(0, 0, 180f);
planeH.transform.position = new Vector3(i, blockHeight, j);
*/
}
}
}
GetComponent<NavMeshSurface>().BuildNavMesh();
}
試行錯誤として、足場を動的に配置してオクルージョンカリングにより処理負荷軽減できないか試してみましたが、処理負荷増となったため不採用としました。(コメントアウトの処理です)
更に処理負荷軽減するとしたら、壁の立方体を平面に変更するなどありますが、結構大変そうなので今回はここまで。
※前回のスクリプトではResourcesで取り出した素材の変数がmaterialでしたが、可読性の観点からmatAssetsに変更しました。
他にもあるかもしれませんが適宜読み替えて下さい。
最後に
いかがでしたでしょうか。
技術的にはとてもシンプルで、乱数やマテリアルの大きさを変更するなどの対応をしてみました。
参考にして頂けると嬉しいです:)
以上、だらはでした。
ディスカッション
コメント一覧
まだ、コメントがありません