← Back to Blog tutorials

GPU instancing in Unity URP: cut draw calls for repeated props

By BitSoul Team6/16/2026Updated 8/7/20265 min read104 views
GPU instancing in Unity URP: cut draw calls for repeated props

GPU instancing in Unity URP cuts draw calls by rendering hundreds of identical meshes in a single GPU batch — the difference between 60 FPS and a slideshow on mid-range hardware. If your scene has repeated props (trees, rocks, barrels, fence posts), and the Unity profiler shows hundreds of draw calls for geometrically identical meshes, instancing is the fix.

Why draw calls are your enemy

Every time Unity tells the GPU "draw this mesh with this material," that's a draw call. On desktop GPUs you might handle 2,000–3,000 before performance degrades. On mobile, the limit is closer to 200–300.

The trap: a scene with 500 identical barrels doesn't have one draw call per unique mesh — it has 500. Each one carries CPU-side overhead to set state, bind textures, and issue the command. At 500 identical objects, the CPU becomes the bottleneck long before the GPU even breaks a sweat.

The Unity Frame Debugger makes this visible. Open it via *Window → Analysis → Frame Debugger*, hit *Enable*, and look for cascading "Draw Mesh" entries with the same mesh name. That's your target.

Why draw calls are your enemy — illustrated

Key terminology before diving in:

| Term | What it means |
|------|---------------|
| Draw call | One CPU-to-GPU command to render a mesh |
| Batch | Multiple draw calls merged into one GPU submission |
| GPU instancing | Rendering N copies of one mesh in a single draw call with per-instance data (transform, color) on the GPU |
| SRP Batcher | Unity's alternative batching for URP — compatible materials share a CBUFFer, reducing state changes |

How GPU instancing works in Unity URP

GPU instancing pushes per-instance data (the transform matrix, any per-object material properties) into a structured GPU buffer. The GPU then runs one draw call that iterates over all instances internally — no CPU round-trip per object.

In Unity URP, instancing works alongside the SRP Batcher, not instead of it. The SRP Batcher handles materials with different property values; GPU instancing handles large counts of the same material on the same mesh. They're complementary.

Three conditions must all be true for instancing to kick in:
1. Enable GPU Instancing checked on the material
2. The mesh is a static mesh (or you use `Graphics.DrawMeshInstanced` / `Graphics.RenderMeshInstanced` for dynamic objects)
3. Objects share the same mesh + material combination (no per-object material overrides via `renderer.material` — use `renderer.sharedMaterial`)

How GPU instancing works in Unity URP — illustrated

Step-by-step: enabling GPU instancing in Unity URP

Step 1 — Enable instancing on the material

In the Inspector for any URP Lit or Unlit material, check Enable GPU Instancing. That's it for built-in URP shaders — they already have the `#pragma multi_compile_instancing` directive.

For custom ShaderGraph shaders:
- Open the ShaderGraph
- In the Graph Inspector, check Enable GPU Instancing
- Unity generates the instancing variants automatically on next compile

Step 2 — Mark objects as Static (or use DrawMesh APIs for dynamic)

For environment props that don't move: select them in the scene, tick Static in the Inspector header. Unity's static batching and GPU instancing are separate systems — for instancing specifically, objects don't need to be *static*, but they do need to share materials. Static batching actually prevents instancing because it merges meshes at build time into one combined mesh. Choose one:

For runtime-spawned objects (particles, procedural props), use `Graphics.RenderMeshInstanced`:

```csharp
// Cache the render params once
RenderParams rp = new RenderParams(instancedMaterial);
rp.worldBounds = new Bounds(Vector3.zero, Vector3.one * 1000f);
rp.matProps = new MaterialPropertyBlock();

// In Update or via ComputeShader
Matrix4x4[] matrices = GetInstanceMatrices(); // your data
Graphics.RenderMeshInstanced(rp, mesh, 0, matrices);
```

This bypasses GameObjects entirely — zero MonoBehaviour overhead, pure GPU throughput.

Step 3 — Avoid the `renderer.material` trap

Accessing `renderer.material` (not `renderer.sharedMaterial`) creates a material clone per object. That breaks instancing immediately — Unity can't batch materials with different instance IDs.

```csharp
// WRONG — creates unique material per object, kills instancing
renderer.material.color = tint;

// CORRECT — use MaterialPropertyBlock for per-instance overrides
MaterialPropertyBlock mpb = new MaterialPropertyBlock();
renderer.GetPropertyBlock(mpb);
mpb.SetColor("_BaseColor", tint);
renderer.SetPropertyBlock(mpb);
```

`MaterialPropertyBlock` lets you vary per-instance data (color, UV offset, float params) without breaking the batch. Unity serializes these into the instanced data buffer automatically.

When instancing fails — and what to do instead

GPU instancing has hard limits:

Skinned meshes — instancing doesn't work on `SkinnedMeshRenderer`. For large crowds, use Vertex Animation Textures (VATs) to bake animations into textures, then render with `MeshRenderer` + instancing.

Shadow casting — by default, each instanced object still generates shadow draw calls. For thousands of distant props, disable shadow casting on the renderer or use LOD groups with shadows disabled at LOD2+.

1023 instance limit per batch — `Graphics.DrawMeshInstanced` caps at 1023 instances per call. `Graphics.RenderMeshInstanced` (Unity 2022+) removes this limit via indirect rendering.

SRP Batcher conflicts — the SRP Batcher and GPU instancing are mutually exclusive on a per-object basis. If the SRP Batcher is active (it's on by default in URP), instancing only activates for objects using `Graphics.DrawMeshInstanced`. For scene GameObjects, the SRP Batcher takes priority. Profile both paths — for 10–50 objects, SRP Batcher usually wins; for 200+ identical objects, force instancing via the DrawMesh APIs.

Check which path your objects are using: in the Frame Debugger, look for "Instanced" vs "SRP Batch" labels on draw calls.

Quick checklist before profiling

Browse the BitSoul marketplace for 747 free GLB props — all game-ready and optimized for instancing workflows in Unity, Unreal Engine 5, and Godot.

---

*This post is part of the Ultimate Guide to Free 3D Game Assets — BitSoul's complete reference for formats, texturing, rigging, optimization, and engine integration.*

Tags: optimization unity game-assets tutorials workflow 3d-models

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