Quick answer: LOD transitions depend on screen-space size, not world distance. Check QualitySettings.lodBias, call LODGroup.RecalculateBounds() after runtime mesh changes, and verify the LODGroup’s Size field matches the actual model bounds.

Here is how to fix Unity LOD Group not switching between levels. You set up a tree asset with three LODs — full detail, medium, and a billboard. You drag it into the scene, move the camera far away, and it stays on LOD0 forever. Or the opposite: it snaps to the lowest LOD even when the camera is close. The LOD Group preview in the Inspector shows the percentages you set, the meshes are assigned to each level, and yet the runtime behavior is wrong. This is almost always a screen-size math problem, not a Unity bug.

The Symptom

Your LOD Group’s transitions do not happen at the distances you expect. Possible variants: only LOD0 renders regardless of camera distance, the game snaps directly from LOD0 to Culled with no intermediate levels, the transitions happen at radically different distances for identical-looking objects, or LOD levels switch correctly in the editor Scene View but not in the built player.

The LOD Group Scene View gizmo (the colored bars showing transition thresholds) may show the correct percentages, which makes this more confusing. Those percentages are screen-space sizes, not distances, so the gizmo is correct and the scene behavior is correct — just not what you expected.

What Causes This

LOD is screen-space, not distance. Unity’s LOD Group decides which level to show based on how big the object appears on screen, as a fraction of screen height. A tall tree viewed from the side has a different screen-space size than the same tree viewed from above, even at the same camera distance. Field of view also matters — a wider FOV makes everything smaller on screen, pushing LOD transitions closer.

QualitySettings.lodBias. This multiplier adjusts how aggressively LODs switch. A bias of 2 keeps higher-detail LODs at longer distances; a bias of 0.5 switches to lower LODs sooner. If your quality preset sets bias to 2, your carefully tuned 50% / 25% / 10% thresholds effectively become 100% / 50% / 20%, and you stay on LOD0 far longer than intended. Default bias varies by quality level, so it can be different in the build than in the editor.

Wrong bounds after runtime mesh change. LODGroup caches a size field computed from the combined bounds of LOD0’s renderers. If you swap the mesh at runtime (e.g. skinned mesh retargeting, mesh combining), the bounds stop matching the actual renderer. Calling LODGroup.RecalculateBounds() fixes this. If you forget, the LOD calculation uses stale size and picks the wrong level.

Hierarchy scale. If the LODGroup is on a parent that has a non-identity scale, the effective size of the group is scaled, but the Size field shown in the Inspector is the unscaled value. Transitions still use the effective scaled size, so the numbers do not match visually. Rescaling a LOD Group hierarchy without recalculating bounds causes wrong transitions.

Camera-scoped LOD Bias. Cinemachine virtual cameras and some custom camera rigs can override Camera.lodBias on individual cameras. The camera that renders the frame may have a different bias than the default, and you may not know unless you check.

The Fix

Step 1: Check Quality Settings bias. Open Edit > Project Settings > Quality and look at the LOD Bias for each level. For initial LOD tuning, set all levels to 1.0. Any other value is an intentional quality tradeoff, and you should know when you are making it.

// Log the active bias at runtime
Debug.Log($"LOD Bias: {QualitySettings.lodBias}, " +
    $"Max LOD: {QualitySettings.maximumLODLevel}");

Step 2: Call RecalculateBounds after mesh changes. Any runtime change to the size of your LOD0 mesh requires recalculating the bounds. This includes skinned mesh pose changes only if you want dynamic LOD bounds (uncommon), but more typically procedural meshes, mesh combining, and runtime-scaled props.

using UnityEngine;

public class ProceduralTree : MonoBehaviour
{
    private LODGroup lodGroup;

    void Awake() => lodGroup = GetComponent<LODGroup>();

    public void RebuildMeshes()
    {
        // ... regenerate LOD meshes ...

        // Critical: refresh LODGroup size from renderer bounds
        lodGroup.RecalculateBounds();
    }
}

Step 3: Use ForceLOD to validate each level. Before debugging transitions, confirm each LOD renders correctly on its own. Temporarily force each level and check the visual result.

lodGroup.ForceLOD(0); // Lock to LOD0
lodGroup.ForceLOD(1); // Lock to LOD1
lodGroup.ForceLOD(-1); // Return to automatic

If a forced LOD level looks wrong, the problem is with that level’s mesh or renderers, not the transition logic. If every level looks correct when forced but the group refuses to switch, the problem is the screen-size threshold math.

Step 4: Inspect screen-space size at runtime. Unity’s LOD system compares the object’s screen-space size against the transition thresholds. You can compute and log this value to see what percentage the LOD system is seeing.

float GetScreenSize(Camera cam, LODGroup group)
{
    float relativeHeight = group.size /
        (2.0f * Vector3.Distance(cam.transform.position,
            group.transform.position) *
            Mathf.Tan(cam.fieldOfView * Mathf.Deg2Rad * 0.5f));
    return relativeHeight * QualitySettings.lodBias;
}

Compare this value to the transition thresholds you set. If the object appears as 30% of screen height and your transition from LOD0 to LOD1 is at 50%, LOD1 should be active. If it is not, maximumLODLevel is probably clamping.

Cross-Fading and Animated Crossfade

If you enable animated crossfading, the LODGroup holds both levels visible for a short time during transition. If the crossfade duration is long and your transitions happen frequently (due to close-range LOD tuning), the GPU can end up rendering multiple LOD levels at once — worse than just rendering LOD0. Keep crossfade durations short (0.2–0.5 seconds) and avoid transitions that trigger frequently.

Build vs. Editor Discrepancy

If LODs switch in the editor but not the build, the build’s active quality level has a different LOD bias than the editor. Check PlayerSettings for the per-platform default quality level. Some developers set quality to Ultra in editor and Medium in builds without realizing the LOD bias differs.

“LOD is screen-space. Measure screen-space. Stop measuring distance and you will stop being surprised.”

Related Issues

For terrain-specific LOD, see Unity Terrain Trees Disappearing at Distance. For mesh-level performance issues, Transform Hierarchy Deep Performance covers related deep-scene issues.

Start with bias 1.0, thresholds 50/25/10, and ForceLOD to validate. Tune from a known baseline.