【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に変更しました。
他にもあるかもしれませんが適宜読み替えて下さい。

最後に

いかがでしたでしょうか。
技術的にはとてもシンプルで、乱数やマテリアルの大きさを変更するなどの対応をしてみました。
参考にして頂けると嬉しいです:)

以上、だらはでした。

スポンサーリンク

応用

Posted by daraha_gm