egametang/ET · warning · Exception

rcBuildCompactHeightfield: Heightfield has too many layers {

Error message

rcBuildCompactHeightfield: Heightfield has too many layers {tooHighNeighbour} (max: {MAX_LAYERS})

What it means

Thrown at the end of rcBuildCompactHeightfield when a compact-cell neighbour span index (lidx) exceeded MAX_LAYERS during neighbour connectivity. MAX_LAYERS caps how many overlapping walkable spans can stack in a single XZ cell of the compact heightfield; exceeding it means the voxelization produced too many stacked walkable layers for the configuration.

Source

Thrown at Packages/cn.etetet.recast/Scripts/Core/Share/Recast/RecastCompact.cs:159

                                    int lidx = k - nc.index;
                                    if (lidx < 0 || lidx > MAX_LAYERS)
                                    {
                                        tooHighNeighbour = Math.Max(tooHighNeighbour, lidx);
                                        continue;
                                    }

                                    RecastCommon.SetCon(s, dir, lidx);
                                    break;
                                }
                            }
                        }
                    }
                }
            }

            if (tooHighNeighbour > MAX_LAYERS)
            {
                throw new Exception("rcBuildCompactHeightfield: Heightfield has too many layers " + tooHighNeighbour
                                                                                                  + " (max: " + MAX_LAYERS + ")");
            }

            return chf;
        }

        private static int GetHeightFieldSpanCount(RcHeightfield hf)
        {
            int w = hf.width;
            int h = hf.height;
            int spanCount = 0;
            for (int y = 0; y < h; ++y)
            {
                for (int x = 0; x < w; ++x)
                {
                    for (RcSpan s = hf.spans[x + y * w]; s != null; s = s.next)
                    {
                        if (s.area != RC_NULL_AREA)

View on GitHub (pinned to 5cab01f7a8)

Solutions

  1. Increase walkableHeight so closely-stacked spans merge into fewer layers.
  2. Decrease voxel cell size (cs) / cell height (ch) to better separate the layers spatially.
  3. Increase walkableClimb to merge small steps that spawn extra layers.
  4. Simplify the source geometry to remove redundant overlapping walkable surfaces.

Example fix

// before
cfg.walkableHeight = 0.1f; // tiny -> many stacked spans
cfg.cs = 0.3f;

// after
cfg.walkableHeight = 1.5f; // merge thin layers
cfg.cs = 0.2f;            // finer voxels separate real layers
Defensive patterns

Strategy: validation

Validate before calling

// Sanity-check config before building.
if (cfg.walkableHeight < cfg.ch * 2) Debug.LogWarning("walkableHeight very small -> many layers");
if (cfg.ch > cfg.walkableHeight) Debug.LogWarning("cell height > walkableHeight may stack layers");

Type guard

// No type guard (config-tuning). Treat as runtime config validation.

Try / catch

try { RcCompactHeightfield chf = RecastCompact.BuildCompactHeightfield(ctx, walkableHeight, walkableClimb, hf); }
catch (Exception e) when (e.Message.Contains("too many layers"))
{ /* raise walkableHeight / lower cs,ch and retry */ }

Prevention

When it happens

Trigger: A scene with many overlapping walkable surfaces in the same column (stairs, ramps, thin floors) combined with a small walkableHeight and/or large voxel cell size that stacks spans; geometry with near-coincident walkable planes.

Common situations: Cell height too large relative to floor spacing; walkableHeight too small so multiple thin ledges each qualify as walkable; dense multi-floor geometry.

Related errors


AI-assisted analysis of egametang/ET@5cab01f7a8 (2026-08-13). Data as JSON: /api/errors/b90bf3a82649d3eb. Report an issue: GitHub.