Unity Term Book
グラフィックスとエフェクト

Culling

Culling はカメラに見えないものを描画しません——視錐台外や遮蔽された物体の draw call を削減します。Frustum Culling・Occlusion・LOD・layerCullDistances の使い分けを実践的に学べます。図解とシミュレーターで描画スキップを体感し、自学にも使えます。

想像してみてください...

Culling は賢い舞台監督です。舞台上のすべての役者に照明を当てる代わりに、 客席から見える役者だけを照らします。カーテンの裏?消灯。角度外?消灯。 GPU はそれらを知りません——毎フレーム何千ものドローコールが節約されます。

概念の詳細

Frustum Culling は基本——Unity はカメラ視錐台の六平面 (FOV と near/far clip から作る切頭錐体)を各 Renderer の境界ボックスと照合します。 境界が完全に外なら → ドローコールをスキップ。組み込み、常時オン、設定不要。

Occlusion Culling は次の段階——視錐台内でも完全に隠れた物体をスキップ。 Unity は Umbra で遮蔽データを事前計算(ベイク): Window → Rendering → Occlusion Culling → Bake。Static ドロップダウンで occluder / occludee をマーク。 屋内に強く、オープンワールドでは弱め。

LOD (Level of Detail) は関連——完全にカリングする代わりに、 LOD Group が距離に応じてメッシュ複雑度を下げます。LOD0 = フル詳細(近)、LOD1 = 中、LOD2 = 簡易、 LOD3 = ビルボード、Culled = 非表示。距離による品質/性能のトレードオフです。

Backface Culling は GPU レベル——カメラから見て法線が向こうを向く三角形を落とします。 すべてのシェーダーでデフォルトオン、閉じたメッシュのフラグメント作業を約 50% 節約。 Material の “Two Sided” または ShaderLab の Cull Off で無効化。

カリングの種類

📐

Frustum Culling

カメラ視野外のオブジェクトは完全にスキップされる。 自動。セットアップ不要。すべてのプロジェクトで有効。

Camera.layerCullDistances[]

🏗️

Occlusion Culling

壁や建物に隠れたオブジェクトはスキップされる。 ベイクが必要 で Static を指定。屋内シーンに最適。

Static → Occluder/Occludee

📏

LOD Group

カメラから遠いほどポリゴン数を減らす。LOD0→LOD3→Culled。 準備が必要 な複数メッシュ。オープンワールド向き。

LODGroup component

ハンズオン手順

1

Frustum Culling:Camera Far Clip を締める

Camera → Far Clip Plane:1000 から 200–500 に下げて遠い物体をカリング。切れ目はフォグで隠す。

2

Occlusion Culling 用に Static をマーク

壁/床/天井を選択 → Inspector → Static → Occluder Static と Occludee Static。

3

遮蔽データをベイク

Window → Rendering → Occlusion Culling → Bake。Occlusion Area でベイク体積を制御。

4

LOD Group を追加

Add Component → LOD Group → 各スロットに LOD0/1/2 メッシュをドロップし、画面サイズ % を調整。

5

Rendering Statistics で計測

Game View → Stats:カメラを動かし "Batches" と "Tris" を観察。Scene ビューの Occlusion Culling Visualization も。

インタラクティブシミュレーター

カメラをシーン周りでオービットし、どの物体が視錐台カリング / 遮蔽カリングされるかを確認。

Visible: 0

Culled: 0

Visible Frustum Culled Occlusion Culled

コード例

基本

レイヤーごとのカリング距離を設定し、レンダラーの可視性を確認。

using UnityEngine;

public class CullingSetup : MonoBehaviour
{
  void Start()
  {
      Camera cam = Camera.main;

      // Per-layer cull distance
      // 32 entries (32 layers) — 0 = use Far Clip
      float[] distances = new float[32];
      distances[8]  = 50f;   // Layer 8 "SmallProps": cull after 50m
      distances[9]  = 150f;  // Layer 9 "MediumProps": cull after 150m
      distances[10] = 0f;    // Layer 10: use Camera.farClipPlane
      cam.layerCullDistances = distances;

      // Spherical culling: from camera center, not frustum planes
      cam.layerCullSpherical = true;
  }

  // Is this renderer currently visible to a camera?
  void CheckVisibility(Renderer rend)
  {
      if (rend.isVisible)
          Debug.Log(rend.name + " is being rendered");
  }
}

コード例

上級

コードから LOD Group を設定し、LOD レベルを強制(デバッグ / カットシーン)。

using UnityEngine;

public class DynamicLOD : MonoBehaviour
{
  public Renderer[] lod0, lod1, lod2;
  LODGroup group;

  void Awake()
  {
      group = GetComponent<LODGroup>();
      if (group == null)
          group = gameObject.AddComponent<LODGroup>();

      // Configure LOD levels from code
      LOD[] lods = new LOD[3];
      lods[0] = new LOD(0.5f, lod0);  // 50%+ screen → LOD0
      lods[1] = new LOD(0.15f, lod1); // 15-50% → LOD1
      lods[2] = new LOD(0.03f, lod2); // <3% → LOD2, <0 → culled
      group.SetLODs(lods);
      group.RecalculateBounds();
  }

  // Force a specific LOD (debug or cutscene close-up)
  public void ForceLOD(int level)
  {
      group.ForceLOD(level); // -1 = disable force, use automatic
  }
}

📌 要点

  • Frustum Culling: 自動、設定不要
  • Occlusion Culling: ベイクが必要、屋内向き
  • LOD Group: 距離でポリゴン数を下げる
  • layerCullDistances: レイヤーごとのカリング範囲
  • renderer.isVisible: 描画中なら true

⚠️ よくあるミス

  • ❌ Occlusion をベイクしたのに何もカリングされない

    Camera → Occlusion Culling = true を忘れた

    ✅ Camera Inspector → Rendering → Occlusion Culling にチェック

  • ❌ LOD ポップ(ズーム時にメッシュが跳ぶ)

    LOD 遷移が広すぎ、LOD Fade なし

    ✅ LOD Group で "Fade Mode = Cross Fade" を設定してブレンド