Quick answer: SkinnedMeshRenderer bounds are calculated once at import from the bind pose. Animations that move vertices far from the bind pose can push geometry outside the bounding box, causing Unity to cull the mesh while it is still visible. Enable Update When Offscreen on the renderer, or manually expand localBounds to encompass all animation poses.

Here is how to fix Unity SkinnedMeshRenderer bounds being wrong. Your character runs an attack animation with a wide sword swing. The camera pans slightly and the entire character vanishes. Pan back and it reappears. The mesh is being frustum-culled because its bounding box does not cover the extended pose. This is one of the most common visual bugs in 3D Unity projects and the fix is straightforward once you understand what Unity is actually checking.

The Symptom

A skinned mesh disappears when the camera is at certain angles even though the mesh should be visible. Common patterns include:

Selecting the object in the editor and checking the wireframe bounding box reveals that the bounds are far smaller than the animated mesh extent.

What Causes This

Bind-pose bounds calculation. When Unity imports an FBX or other mesh, it calculates the SkinnedMeshRenderer’s bounding box from the bind pose — the default T-pose or A-pose. This bounding box is stored in sharedMesh.bounds and never updated automatically during gameplay. If an animation stretches the mesh beyond that box, Unity does not know.

Root bone assignment. The bounds are relative to the root bone. If the root bone is set to the wrong transform (for example the armature root instead of the hips), the bounds center can be offset from where the mesh actually renders. A misassigned root bone shifts the bounding box away from the visible geometry.

Frustum culling. Unity checks each renderer’s AABB against the camera frustum every frame. If the AABB is outside the frustum, Unity skips rendering entirely. With tight bind-pose bounds, the mesh gets culled even though animated vertices are within the frustum.

LOD and occlusion interactions. LOD groups use the renderer bounds to decide which LOD to show. Wrong bounds can cause LOD popping or the wrong LOD being selected. Occlusion culling also relies on bounds, so an undersized box can cause objects behind an occluder to disappear prematurely.

The Fix

Step 1: Enable Update When Offscreen for debugging. Select the SkinnedMeshRenderer and check Update When Offscreen. This forces Unity to skin the mesh every frame regardless of culling. If the disappearing stops, you have confirmed a bounds problem.

SkinnedMeshRenderer smr = GetComponent<SkinnedMeshRenderer>();
smr.updateWhenOffscreen = true; // force update, confirm it is a bounds issue

Leave this on for player characters where the cost is acceptable. For NPCs and background characters, move to Step 2.

Step 2: Manually expand localBounds. Set the bounds large enough to contain the mesh in all animation poses. You can do this in the Inspector or in code during Awake.

void Awake()
{
    SkinnedMeshRenderer smr = GetComponent<SkinnedMeshRenderer>();
    Bounds expanded = smr.localBounds;
    expanded.extents = new Vector3(2f, 2f, 2f); // generous padding
    smr.localBounds = expanded;
}

Overly generous bounds waste a small amount of culling efficiency — objects are rendered when they could have been skipped — but the visual correctness gain is worth it. Find the smallest bounds that cover all poses.

Step 3: Compute bounds from animation clips at edit time. For production accuracy, sample every animation clip at regular intervals, bake the mesh, and take the enclosing AABB. This gives you tight but correct bounds.

// Editor script: compute bounds from all animation clips
public static Bounds ComputeAnimationBounds(SkinnedMeshRenderer smr, AnimationClip[] clips)
{
    Bounds result = smr.localBounds;
    Mesh bakedMesh = new Mesh();

    foreach (AnimationClip clip in clips)
    {
        for (float t = 0f; t < clip.length; t += 0.1f)
        {
            clip.SampleAnimation(smr.gameObject, t);
            smr.BakeMesh(bakedMesh);
            bakedMesh.RecalculateBounds();
            result.Encapsulate(bakedMesh.bounds);
        }
    }
    Object.DestroyImmediate(bakedMesh);
    return result;
}

Step 4: Verify root bone assignment. In the SkinnedMeshRenderer component, check that Root Bone points to the correct transform — typically the Hips bone. If it points to the armature root or an empty GameObject, the bounds center will be wrong. Reassign it and the bounds will shift to the correct location.

Runtime Recalculation

For characters with procedural animation or ragdoll states where poses are unpredictable, recalculate bounds periodically at runtime:

private Mesh _bakedMesh;
private SkinnedMeshRenderer _smr;
private float _boundsTimer;

void Update()
{
    _boundsTimer -= Time.deltaTime;
    if (_boundsTimer > 0f) return;
    _boundsTimer = 0.25f; // recalculate 4 times per second

    if (_bakedMesh == null) _bakedMesh = new Mesh();
    _smr.BakeMesh(_bakedMesh);
    _bakedMesh.RecalculateBounds();

    Bounds local = _bakedMesh.bounds;
    local.extents *= 1.2f; // 20% padding
    _smr.localBounds = local;
}

BakeMesh has a CPU cost. Running it every frame on many characters is expensive. Throttle to a few times per second and only do it for characters in ragdoll or procedural states.

Multi-Part Characters

Characters with separate SkinnedMeshRenderers for head, body, and equipment need bounds set on each renderer independently. A tight body bound does not cover an oversized weapon mesh on a child renderer. Either set generous bounds on each part or parent them under a single renderer with combined bounds.

“Bind-pose bounds are a performance optimization. When the optimization hides your character, the optimization is wrong — expand the box.”

Related Issues

For mesh renderer culling issues with static meshes, check your occlusion culling bake data. For LOD popping related to bounds, ensure LOD group bounds match the skinned mesh bounds. For disappearing particles, the same frustum culling logic applies to ParticleSystemRenderers — expand their bounds or set renderMode appropriately.

Update When Offscreen for debugging. Manual localBounds for production. Root bone for centering. BakeMesh for ragdolls.