Quick answer: The progressive lightmapper hangs at “Adding to scene 95%” when the GI cache is corrupt, the GPU lightmapper runs out of VRAM during atlas composition, or a mesh has invalid UV2 data (missing channel, NaN values, or huge overlapping islands) that crashes the atlas writer. Clear the GI cache, switch the scene to the CPU lightmapper to confirm it is GPU-specific, and bisect by enabling Contribute GI on half the meshes at a time to find the offender.

Here is how to fix Unity light baking when it gets stuck at 95 percent forever. You hit Generate Lighting on a scene that baked fine yesterday, you watch the progress bar climb steadily, and at 95% it stops. The thread is alive, the editor is responsive, the progressive lightmapper just sits there forever. Sometimes you can wait an hour and it never moves. Sometimes the editor crashes after thirty minutes. The 95% mark is the worst place to hang because it usually means the actual radiance computation finished and something simple is going wrong during the final write step.

The Symptom

The 95% hang has a few near-identical variants. Distinguishing between them helps you pick the right fix:

Progress bar reads “Adding to scene” and stops. The phase name in the progress dialog is the most useful clue. “Adding to scene” is the atlas composition step where Unity writes the final lightmap textures out to the project. Hangs here are atlas-related: UV problems, VRAM exhaustion, or disk-side issues with the lightmap output folder.

Progress bar reads “Cleanup” and stops. Different phase, different cause. Cleanup hangs are usually the GI cache trying to flush intermediate data and finding it cannot write (permissions, full disk, or a locked file held by another process).

Editor responsive but bake never completes. You can interact with the editor — menus work, scene view rotates — but the progress bar is frozen. This is the “something is stuck in a worker thread but the main thread is fine” pattern, typical of GPU driver hangs or thread deadlocks.

Editor freezes entirely at 95%. The whole editor stops responding. This is the worst case — usually a GPU lightmapper VRAM exhaustion that wedged the driver, or a hard NaN propagation that crashed a worker.

What Causes This

Corrupt GI cache. The GI cache stores intermediate lighting computations indexed by a hash of the scene state. If a previous bake was interrupted (you closed the editor, the process was killed, the system crashed), the cache can end up with partially-written entries that look valid by hash but contain garbage. The next bake reads them, gets nonsense, and either hangs trying to make sense of it or writes broken atlases.

GPU lightmapper VRAM exhaustion. The progressive GPU lightmapper allocates a contiguous VRAM region for the atlas plus working buffers. A 4096×4096 RGBA32F atlas is 256 MB by itself; with multiple atlases and per-bounce working storage, a complex scene easily consumes 4–8 GB. If your GPU does not have that available (because of other applications, a 4 GB card, or a shared system), the driver may hang the bake instead of failing cleanly.

NaN UVs on a mesh. A mesh whose UV2 channel contains NaN or infinity values feeds garbage coordinates into the atlas packer. The packer either loops forever trying to fit a degenerate quad or writes outside the atlas bounds and corrupts memory. NaN UVs usually come from procedurally generated meshes where a degenerate triangle (zero area) caused a divide-by-zero in the lightmap UV generator.

Missing Generate Lightmap UVs. An imported mesh marked Static but without Generate Lightmap UVs enabled has no UV2 channel at all. The lightmapper either falls back to UV0 (bad) or crashes (worse). The fix is to enable Generate Lightmap UVs in the FBX importer and reimport.

The Fix

Step 1: Clear the GI cache. Open Edit > Preferences > GI Cache. Click Clean Cache. This removes every cached lighting computation but leaves your existing lightmap assets untouched. Bake again. If the hang was due to corrupt cache entries, this single step often fixes it on the first retry. The next bake will be slower because the cache rebuilds from scratch.

Step 2: Switch lightmapper backends. In the Lighting window, find Lightmapper and switch from Progressive GPU to Progressive CPU. Bake again. If the CPU bake completes but the GPU bake hangs, you have a GPU-specific issue (VRAM, driver, or atlas size). Drop Lightmap Resolution in half and try the GPU path again to see if it now fits in memory.

Step 3: Validate UV2 on every static mesh. Write a small editor script that walks every Static MeshRenderer in the scene and inspects the UV2 channel:

using UnityEngine;
using UnityEditor;

public class Uv2Validator
{
    [MenuItem("Tools/Validate Lightmap UVs")]
    public static void Validate()
    {
        MeshRenderer[] renderers =
            Object.FindObjectsByType<MeshRenderer>(FindObjectsSortMode.None);
        int bad = 0;

        foreach (MeshRenderer mr in renderers)
        {
            if (!mr.gameObject.isStatic) continue;

            MeshFilter mf = mr.GetComponent<MeshFilter>();
            if (mf == null || mf.sharedMesh == null) continue;

            Mesh mesh = mf.sharedMesh;
            Vector2[] uv2 = mesh.uv2;

            if (uv2 == null || uv2.Length == 0)
            {
                Debug.LogError($"Missing UV2 on {mr.name}", mr);
                bad++;
                continue;
            }

            for (int i = 0; i < uv2.Length; i++)
            {
                if (float.IsNaN(uv2[i].x) || float.IsNaN(uv2[i].y) ||
                    float.IsInfinity(uv2[i].x) || float.IsInfinity(uv2[i].y))
                {
                    Debug.LogError(
                        $"NaN/Inf UV2 at vertex {i} on {mr.name}", mr);
                    bad++;
                    break;
                }
            }
        }

        Debug.Log($"UV2 validation finished: {bad} problematic meshes");
    }
}

Run this once per scene before baking. Click any logged error to highlight the offending GameObject in the hierarchy, then either re-import its mesh with Generate Lightmap UVs enabled or fix the source asset in your DCC tool.

Bisecting the Offending Mesh

If the validator finds nothing but the bake still hangs, the problem is harder to diagnose — usually a mesh with valid UVs whose atlas-packed footprint is enormous. Bisect:

Disable Contribute GI on half the static meshes in the scene. Bake. If it completes, the offender is in the disabled half — re-enable, disable a quarter, bake again. If it hangs, the offender is in the enabled half — disable a quarter from the enabled half, bake. After about log2(N) iterations you have isolated a single mesh.

Once you have the mesh, inspect its lightmap parameters. A mesh with Scale In Lightmap = 50 and a 512×512 lightmap resolution requires a 25,600-pixel-wide atlas allocation, which can simply not fit. Drop the scale or split the mesh into multiple smaller meshes.

Configuring for Large Scenes

For genuinely large scenes (open-world levels, architectural visualizations) the practical answer is to bake in passes. In the Lighting window, check Auto Generate off, set Indirect Resolution to 1 for an iteration pass to find issues quickly, then ramp up to 24 for the final bake. Lower Lightmap Size from 4096 to 2048 if your scene has hundreds of small meshes — more atlases of smaller size pack better than one giant one.

using UnityEngine;
using UnityEditor;

// Programmatic lighting settings for batch-baking pipelines.
public static class BakeConfig
{
    [MenuItem("Tools/Configure for Large Scene Bake")]
    public static void Configure()
    {
        LightingSettings settings = Lightmapping.lightingSettings;
        settings.lightmapper = LightingSettings.Lightmapper.ProgressiveCPU;
        settings.indirectResolution = 1f;
        settings.lightmapResolution = 20f;
        settings.lightmapMaxSize = 2048;
        settings.directionalityMode = LightmapsMode.NonDirectional;

        Debug.Log("Switched to CPU + low res for diagnostic bake");
    }
}

“A bake that hangs at 95% is a bake that finished radiance and broke writing the result. The fix is almost always upstream of the lightmapper — in your meshes, your cache, or your VRAM budget.”

Related Issues

If your bake completes but the lightmaps look wrong (seams, shadow leaks, dark patches), the underlying cause is often the same UV2 issues that cause hangs — just less severe. Use the validator above as a routine pre-bake check, and treat any UV2 warning as a bake-blocker until fixed.

Clear the GI cache, swap to the CPU lightmapper, run the UV2 validator — in that order, every time the bake hangs.