← Back to Blog 3d-modeling

Occlusion Culling for Game Engines: Boost FPS in Unity, Unreal Engine 5, and Godot 4

By BitSoul Team5/3/2026Updated 8/2/20266 min read525 views
Occlusion Culling for Game Engines: Boost FPS in Unity, Unreal Engine 5, and Godot 4

You've done everything right: optimized your meshes, baked your lightmaps, compressed your textures. Yet your frame rate still tanks the moment the player enters a dense city or interior level. The culprit is almost always geometry the GPU is rendering that the camera will never actually display. Occlusion culling is the system that fixes this — and most developers either skip it or set it up wrong.

What Is Occlusion Culling and Why It Matters

Occlusion culling is the process of identifying and skipping the rendering of objects that are completely hidden behind other geometry. The camera frustum already culls objects outside the view — occlusion culling goes further, removing objects that are *inside* the frustum but hidden by walls, terrain, or large props.

In a city level with 800 buildings, the camera at street level can only see a fraction of the geometry. Without occlusion culling, all 800 buildings still submit draw calls to the GPU. With occlusion culling, only the 60 or so visible buildings do. The performance difference compounds with every additional object in the scene.

Occlusion culling matters most in:
- Dense interiors with lots of walls (dungeons, bunkers, buildings)
- Open-world cities where buildings block each other
- Procedurally generated levels with unpredictable sightlines
- Corridor shooters with tight geometry

It is less relevant for open terrain with no occluding geometry — there, frustum culling and LODs do the heavy lifting.

| Scenario | Expected FPS gain from occlusion culling |
|---|---|
| Open terrain with hills | 5–15% |
| Dense forest | 20–35% |
| Urban street level | 40–60% |
| Indoor dungeon | 50–70% |

Setting Up Occlusion Culling in Unity

Setting Up Occlusion Culling in Unity — illustrated

Unity uses a precomputed occlusion culling system that bakes visibility data at editor time. This is CPU-efficient at runtime but requires setup.

Step 1 — Mark occluders and occludees. Select any large solid object (walls, floors, terrain chunks) and enable *Occluder Static* in the inspector. For objects you want hidden when not visible, enable *Occludee Static*. Small props only need *Occludee Static*; they're too small to block anything.

Step 2 — Open the Occlusion Culling window. Go to *Window > Rendering > Occlusion Culling*. Under the *Bake* tab, set your smallest occluder size (typically 1–2 m for indoor scenes, 5–10 m for exteriors) and smallest hole size (gaps a camera can see through).

Step 3 — Bake. Hit *Bake*. Unity generates an occlusion data asset. For large open-world levels, split your scene into multiple additive scenes and bake each independently.

Step 4 — Verify with the visualizer. In the Scene view, enable *Occlusion Culling > Visualize*. Move the camera — occluded objects should go grey. If nothing is grey, your occluder objects aren't marked correctly.

```csharp
// You can also trigger manual culling checks at runtime
// For dynamic occluders (e.g. a door that opens), disable/enable MeshRenderer
void OnDoorOpen()
{
// Remove dynamic occluder contribution
GetComponent<OcclusionPortal>().open = true;
}
```

Unity's occlusion portals are particularly useful for doors and windows — they let you define explicit openings in otherwise solid occluder geometry.

Occlusion Culling in Unreal Engine 5

UE5 uses a hardware-based Hierarchical Z-Buffer (HZB) occlusion system by default. Unlike Unity's baked approach, UE5 queries the GPU each frame to determine visibility. This makes it dynamic and accurate but adds GPU overhead — a tradeoff worth understanding.

Hardware occlusion queries are enabled by default. UE5 renders a depth prepass, builds an HZB mip chain, and tests object bounding boxes against it. Objects whose bounding box is fully occluded are skipped.

Key console variables for tuning:

```
; Enable/disable hardware occlusion queries
r.HZBOcclusion 1

; Rounds up occlusion test latency (frames) — higher = less accurate but cheaper
r.OneFrameThreadLag 1

; Min screen size for occlusion testing (skip tiny objects)
r.StaticMeshLODDistanceScale 1.0

; Visualize occluded primitives in editor
r.VisualizeOccludedPrimitives 1
```

For Nanite geometry, occlusion is handled automatically at the triangle cluster level — Nanite's visibility buffer already culls occluded clusters before shading. If you're using Nanite meshes, don't worry about per-mesh occlusion setup; focus on non-Nanite objects (skeletal meshes, translucents, particles).

For large open worlds, combine HZB with Hierarchical Level of Detail (HLOD) proxies so distant clusters of geometry are tested as single proxy meshes rather than hundreds of individual actors.

Occlusion Culling in Godot 4

Godot 4 removed the old Godot 3 occlusion culling system and replaced it with OccluderInstance3D, a node-based occluder you place manually in the scene. It's simpler than Unity's bake system but requires deliberate placement.

Step 1 — Add OccluderInstance3D nodes. For each major solid object (wall segments, pillars, large props), add an `OccluderInstance3D` as a child or sibling. Assign a shape — typically `OccluderPolygon3D` for flat walls or `ArrayOccluder3D` for custom shapes.

```gdscript
# You can also create occluders via script for procedural geometry
var occluder = OccluderInstance3D.new()
var polygon = OccluderPolygon3D.new()
polygon.vertices = PackedVector2Array([
Vector2(-5, -3),
Vector2(5, -3),
Vector2(5, 3),
Vector2(-5, 3)
])
occluder.occluder = polygon
add_child(occluder)
```

Step 2 — Enable occlusion culling in Project Settings. Go to *Project Settings > Rendering > Occlusion Culling* and enable *Use Occlusion Culling*. Set the BVH build quality — *High* is recommended for static scenes.

Step 3 — Use the occlusion culling debug view. In the editor's viewport menu, enable *Debug > Occlusion Culling* to see which objects are being culled in real time.

Godot 4's approach is more manual but gives you precise control. For procedurally generated levels, build occluders dynamically via script when the level loads.

Common Mistakes and Optimization Tips

Common Mistakes and Optimization Tips — illustrated

Occlusion culling adds overhead of its own — done wrong, it costs more than it saves. Here's what to avoid:

Over-testing small objects. Every occludee adds a CPU or GPU test. Set a minimum size threshold — objects smaller than 0.5 m² rarely justify the test cost.

Occlusion popping. When objects snap in and out of visibility based on bounding box tests, players notice. Mitigate this by increasing bounding boxes slightly or using a per-frame visibility fade.

Not combining with LODs. Occlusion culling and LODs are complementary, not competing. Use occlusion culling to skip invisible objects entirely and LODs to reduce triangle counts on distant-but-visible objects. Both are needed in dense scenes.

Forgetting dynamic objects. In Unity, dynamic objects (enemies, vehicles) aren't covered by the static bake — you need dynamic occlusion portals or per-object occlusion checks. In UE5, HZB handles dynamic objects automatically.

Checklist: occlusion culling readiness
- [ ] Large solid geometry marked as occluders
- [ ] Minimum occluder size tuned to scene scale
- [ ] Culling visualizer verified — objects are actually being culled
- [ ] Combined with LOD system
- [ ] Dynamic objects handled separately (Unity)
- [ ] Performance profiled before and after bake/setup

For pre-built 3D assets that are already optimized for occlusion (correct normals, clean geometry, no degenerate faces), browse the collection at BitSoul Marketplace. Assets there are game-ready and won't introduce unexpected occlusion artifacts.

Conclusion

Occlusion culling is one of the highest-leverage optimizations available for scene-heavy game levels. Unity's baked system is ideal for static architecture, UE5's HZB handles dynamic scenes automatically, and Godot 4's manual occluders give precise control for custom workflows. The key in all three is validation — use the built-in visualizers to confirm objects are actually being culled, not just assumed to be.

For production-ready assets that pair well with these workflows, visit BitSoul Marketplace to find game-ready GLB, FBX, and Unreal-native packs ready to drop into your next level.

Tags: occlusion culling unity unreal engine 5 godot 4 game optimization rendering performance 3d game development

Skip the modelling — download it instead

A free BitSoul account gets you 2 game-ready models every month plus 25 AI Engine credits to generate one of your own, no card required. Clean topology, PBR textures, and GLB downloads that drop straight into Unreal, Unity, Godot or Blender — plus OBJ and 3D-printable STL export.

Create a free account → Browse 846 models