Quick answer: Default Cooking Options on MeshCollider should stay on. Disabling EnableMeshCleaning, WeldColocatedVertices, or CookForFasterSimulation trades collision correctness for cooking speed and is rarely worth it. For runtime meshes, use Physics.BakeMesh on a worker thread before assigning.
Here is how to fix Unity MeshColliders that produce wrong collisions, ghost contacts, or visible interpenetration. Someone unticked the Cooking Options checkboxes thinking it would speed up collider creation. The collider does cook faster but with weird artifacts. The right fix is to leave defaults on, and use Physics.BakeMesh for genuinely runtime meshes.
The Symptom
MeshCollider on a complex mesh has wrong contacts. Bullets pass through walls, characters fall through floors, or contact normals point the wrong way.
What Causes This
Cooking Options flags off. Each flag enables a cleanup pass during cook. Disabling them assumes input mesh is already clean — rarely true.
Non-watertight mesh. Holes or T-junctions produce garbage cook output without WeldColocatedVertices.
Runtime hitch from sync cook. Some developers disable flags to avoid cook hitches. The right tool is BakeMesh, not flag disabling.
The Fix
Step 1: Leave Cooking Options enabled. On the MeshCollider, expand Cooking Options:
EnableMeshCleaning = true
WeldColocatedVertices = true
CookForFasterSimulation = true
UseFastMidphase = true
These are the safe defaults. Only disable when you have a specific reason and a guaranteed-clean source mesh.
Step 2: Bake runtime meshes asynchronously.
using UnityEngine;
using Unity.Jobs;
using Unity.Collections;
struct BakeMeshJob : IJob
{
public int meshID;
public bool convex;
public void Execute() { Physics.BakeMesh(meshID, convex); }
}
async void AssignProceduralMesh(MeshCollider mc, Mesh m)
{
var job = new BakeMeshJob { meshID = m.GetInstanceID(), convex = mc.convex };
JobHandle h = job.Schedule();
while (!h.IsCompleted) await Awaitable.NextFrameAsync();
h.Complete();
mc.sharedMesh = m; // reuses baked data, no main-thread cook
}
Step 3: Mark static meshes Static. Static MeshColliders cook once at scene start. Dynamic ones (kinematic Rigidbodies, moved transforms) re-cook on changes — expensive.
Step 4: Use convex for moving objects. Concave MeshColliders cannot be on a non-kinematic Rigidbody. Set convex = true for moving objects, accepting the convex hull approximation.
Step 5: Audit your meshes for cleanliness. Run a mesh validation tool. Holes, double-sided faces, or coincident vertices produce poor cook results regardless of flag settings.
“Cooking Options exist to clean meshes. Leave them on. For runtime meshes, BakeMesh on a worker thread.”
Related Issues
For physics tunneling, see Physics Tunneling. For mesh combine UVs, see CombineMeshes Missing UVs.
Defaults on. BakeMesh for runtime. Static where possible. Collisions reliable.