← Back to Blog guide

Godot 4 mesh instancing: MeshInstance3D vs. MultiMesh

By BitSoul Team6/26/2026Updated 8/1/20264 min read162 views
Godot 4 mesh instancing: MeshInstance3D vs. MultiMesh

Rendering thousands of rocks, trees, or crates efficiently is one of the most common performance challenges in open-world Godot 4 projects — and the answer lies in understanding exactly when to use `MeshInstance3D` versus `MultiMeshInstance3D`. Both nodes render a mesh, but they scale in completely different ways under load.

Godot 4 issues one draw call per `MeshInstance3D` node by default. Place 500 identical rocks as individual `MeshInstance3D` nodes and you're looking at 500 draw calls per frame — before shadow passes, before LODs, before anything else. `MultiMeshInstance3D`, on the other hand, sends all instances of the same mesh to the GPU in a single draw call, no matter how many copies you place. For repeated props (foliage, debris, fence posts, tile floor pieces), that difference can drop your GPU time by 80% or more.

When MeshInstance3D is the right choice

When MeshInstance3D is the right choice — illustrated

`MeshInstance3D` is Godot 4's default mesh renderer and the right tool for unique or infrequently repeated props. Use it when:

```gdscript
# Standard MeshInstance3D placement
var rock = preload("res://assets/rock_01.glb").instantiate()
rock.position = Vector3(10, 0, 5)
add_child(rock)
```

`MeshInstance3D` integrates cleanly with Godot's scene tree. Each node can have its own `CollisionShape3D`, `Area3D`, visibility flags, or script. The cost is one draw call per node, so keep instance counts low.

Surface override materials

You can assign per-surface materials directly on `MeshInstance3D` without touching the original mesh resource — useful when the same GLB prop needs a damaged, snowy, or emissive variant at specific scene locations:

```gdscript
# Override surface 0 material on a specific instance
var mesh_inst = $Props/Rock_Damaged
mesh_inst.set_surface_override_material(0, damaged_mat)
```

This works per-node, which is exactly what makes `MeshInstance3D` inflexible at scale: every override is stored individually in the scene tree.

When MultiMeshInstance3D cuts your draw calls

`MultiMeshInstance3D` is the right tool when you're placing the same mesh repeatedly and don't need per-instance behavior. Foliage, rocks along a riverbank, streetlights, fence posts, scattered debris — any prop repeated 50+ times belongs here.

Internally, Godot batches all instances into a single GPU buffer and renders them with one draw call. The CPU overhead of managing 5,000 rocks drops to near-zero at runtime.

```gdscript
# Set up MultiMeshInstance3D at runtime
var mmi = MultiMeshInstance3D.new()
var mm = MultiMesh.new()
mm.mesh = preload("res://assets/rock_01.glb").meshes[0]
mm.instance_count = 500
mm.transform_format = MultiMesh.TRANSFORM_3D

# Assign transforms in a loop
for i in 500:
var t = Transform3D()
t.origin = Vector3(randf_range(-100, 100), 0, randf_range(-100, 100))
mm.set_instance_transform(i, t)

mmi.multimesh = mm
add_child(mmi)
```

`MultiMesh` also supports per-instance custom data (a `Color` value passed to the shader as `INSTANCE_CUSTOM`), letting you drive variation like wind phase offset, tint randomisation, or damage state through a shader without extra draw calls:

```gdscript
# Pass per-instance wind phase as Color.r
for i in mm.instance_count:
mm.set_instance_custom_data(i, Color(randf(), 0, 0, 0))
```

In your shader, access it with `INSTANCE_CUSTOM.r`.

Choosing between them: a decision checklist

Choosing between them: a decision checklist — illustrated

Use this checklist before placing any repeated prop:

| Condition | Use |
|---|---|
| Unique mesh or fewer than 20 instances | `MeshInstance3D` |
| 50+ identical instances | `MultiMeshInstance3D` |
| Per-instance physics / colliders | `MeshInstance3D` |
| Per-instance animation | `MeshInstance3D` |
| Foliage, rocks, debris scatter | `MultiMeshInstance3D` |
| Needs individual runtime removal | `MeshInstance3D` |
| Wind/shader variation via color data | `MultiMeshInstance3D` |
| Static environment props (repeated) | `MultiMeshInstance3D` |

For the middle range (20–50 instances), profile both. Godot 4's Vulkan renderer reduces the per-draw-call overhead compared to GLES3, so the crossover point varies by target hardware.

Collision with MultiMesh

`MultiMeshInstance3D` has no built-in collision. For scattered props that need physics interaction, use a `StaticBody3D` with a trimesh or convex `CollisionShape3D` placed at matching world positions — separate from the visual MultiMesh. For purely decorative scatter (grass, distant rocks), skip collision entirely and save the CPU budget.

Practical mesh instancing in Godot 4 with free GLB props

Free GLB assets from BitSoul's marketplace drop straight into this workflow. For a typical outdoor scene:

  1. Hero props (interactive barrels, unique boulders, quest items) → `MeshInstance3D` with `CollisionShape3D`
  2. Background scatter (small rocks, pebbles, shrubs, broken crates) → `MultiMeshInstance3D`, no collision
  3. Mid-ground props (fence sections, lamp posts) → `MultiMeshInstance3D` with separate static collision shapes at matching transforms

This split keeps the scene tree readable, collision counts manageable, and GPU draw calls minimal. Monitor your draw call budget in Debug → Visible Draw Calls during scene editing — if you're over 200 for static geometry in a single chunk, a `MeshInstance3D`-heavy scatter is the likely culprit.

For LOD layering on top of this setup, pair `MultiMeshInstance3D` with Godot 4's `GeometryInstance3D.visibility_range_begin` and `visibility_range_end` properties to fade props out beyond a set distance without additional scripting.

Browse BitSoul's marketplace for game-ready GLB props optimised for exactly this kind of instanced scatter — low poly counts, clean UV layouts, and single-material meshes that batch cleanly with `MultiMesh`.

---

*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 game-assets tutorials workflow low-poly

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