U
タブ 04世界とゲームループ7 レッスン — タップで開く
04 / 07 · 10 分
世界とゲームループ

シーンを軽いまま保つ

ここまでのプロジェクト

Assets/

Scenes/

Arena.unity

TerrainLOD Groups

Scripts/

PropScatter.cs

Prefabs/

module kit (6 pieces)

プロジェクトの設定

GPU instancingocclusion bakelayerCullDistances

すでにあるものこのレッスンで追加

アリーナは、灰色の床に 11 個のオブジェクトしかなかったころ、毎秒数百フレームで回っていました。まわりに数百本の木を植えればそうはいきません——このレッスンの 4 つをやるなら別ですが。

12 FPS でしか動かないシーンは、シーンではなくスクリーンショットです。12 と 60 の差のほとんどは、この 4 つで埋まります。

アニメーション図

遠いオブジェクトはもっと単純なメッシュに変わります。プレイヤーは入れ替わりに気づきません。

1. 直す前に測る

  1. 1

    Window▸Analysis▸Profiler を開き、CPU と Rendering の行を見ます。

  2. 2

    Game view の Stats パネルで Batches と Tris を読みます。立ち止まったままではなく、Knight を歩き回らせながら。

  3. 3

    CPU 時間が高い→ draw call が多すぎるか、スクリプトの処理が重い。GPU 時間が高い→ 描画点が多すぎるか、オーバーデローや重い shader のせい。

2. LOD グループ

  1. 1

    プロップを選び、Add Component → LOD Group。

  2. 2

    ポリ数の多いメッシュを LOD 0 へ、中くらいを LOD 1 へ、少ないものを LOD 2 へドラッグします。

  3. 3

    Culled 帯は、オブジェクトが数ピクセル分の高さになった時点で完全に消えるように設定します。

  4. 4

    いちばん得をするのは木、建物、岩です。小石にそこまでする価値はありません。

3. draw call を減らす

  • Static Batching:動かさないオブジェクトには必ず Static をチェックします。Unity が build 時に共有メッシュへまとめてくれます。

  • GPU Instancing:何百と繰り返すもののマテリアルで Enable GPU Instancing を有効に。同じ岩 500 個が draw call 1 回になります。

  • マテリアルが少ないほどバッチも減ります。同じマテリアルの二つは一つにまとまりますが、別々のマテリアルにするとまとまりません。

  • texture はアトラス化しましょう。小道具 12 種を収めた 2048 一枚が、512 を 12 枚より有利です。

4. 遮蔽カリング

  1. 1

    視錐台カリング(画面外のものを描かない)は自動です。遮蔽カリング(壁の裏に隠れたものを描かない)は自動ではありません。

  2. 2

    壁と建物を Occluder Static に指定し、Window▸Rendering▸Occlusion Culling▸Bake を実行します。

  3. 3

    室内や、建物ぎっしりの都市ならやる価値があります。見通しのいい野原では無駄です。

5. カメラの到達距離を短くする

the cheapest optimisation in Unity
// Camera Far = 1000 by default. Most levels need 150.
Camera.main.farClipPlane = 150f;

// hide the ugly cut-off with fog
RenderSettings.fog = true;
RenderSettings.fogMode = FogMode.Linear;
RenderSettings.fogStartDistance = 90f;
RenderSettings.fogEndDistance = 145f;

レイヤー別のカリング距離

C# スクリプト
void Start()
{
    float[] distances = new float[32];      // one entry per layer
    for (int i = 0; i < 32; i++) distances[i] = 150f;

    distances[LayerMask.NameToLayer("SmallProps")] = 35f;   // pebbles vanish early
    distances[LayerMask.NameToLayer("Grass")] = 25f;

    Camera.main.layerCullDistances = distances;
}