egametang/ET · warning · Exception

rcBuildContours: Multiple outlines for region {cont.reg}.

Error message

rcBuildContours: Multiple outlines for region {cont.reg}.

What it means

Thrown in rcBuildContours during region hole-merging when a region (cont.reg) already has an outline contour and a second positive-winding (outline) contour is encountered for the same region. Each region should have exactly one outline; a second indicates the region topology is inconsistent (region IDs were not partitioned cleanly).

Source

Thrown at Packages/cn.etetet.recast/Scripts/Core/Share/Recast/RecastContour.cs:903

                {
                    // Collect outline contour and holes contours per region.
                    // We assume that there is one outline and multiple holes.
                    int nregions = chf.maxRegions + 1;
                    RcContourRegion[] regions = new RcContourRegion[nregions];
                    for (int i = 0; i < nregions; i++)
                    {
                        regions[i] = new RcContourRegion();
                    }

                    for (int i = 0; i < cset.conts.Count; ++i)
                    {
                        RcContour cont = cset.conts[i];
                        // Positively would contours are outlines, negative holes.
                        if (winding[i] > 0)
                        {
                            if (regions[cont.reg].outline != null)
                            {
                                throw new Exception(
                                    "rcBuildContours: Multiple outlines for region " + cont.reg + ".");
                            }

                            regions[cont.reg].outline = cont;
                        }
                        else
                        {
                            regions[cont.reg].nholes++;
                        }
                    }

                    for (int i = 0; i < nregions; i++)
                    {
                        if (regions[i].nholes > 0)
                        {
                            regions[i].holes = new RcContourHole[regions[i].nholes];
                            for (int nh = 0; nh < regions[i].nholes; nh++)
                            {

View on GitHub (pinned to 5cab01f7a8)

Solutions

  1. Raise minRegionArea to discard tiny regions that fragment into multiple outlines.
  2. Reduce contour maxSimplificationError (less aggressive simplification) to avoid splitting outlines.
  3. Adjust region partitioning method (e.g., switch watershed -> monotone) for cleaner IDs.
  4. Increase maxEdgeLength so contour edges merge rather than fragmenting.

Example fix

// before
cfg.minRegionArea = 2;
cfg.maxSimplificationError = 2.0f;

// after
cfg.minRegionArea = 64;
cfg.maxSimplificationError = 1.1f;
Defensive patterns

Strategy: validation

Validate before calling

if (cfg.minRegionArea < 16) Debug.LogWarning("Tiny minRegionArea can fragment regions -> multiple outlines");
if (cfg.maxSimplificationError > 1.5f) Debug.LogWarning("High simplification error may split outlines");

Try / catch

try { var cset = RecastContour.BuildContours(ctx, chf, maxError, maxEdge, buildFlags); }
catch (Exception e) when (e.Message.Contains("Multiple outlines"))
{ /* raise minRegionArea, lower maxSimplificationError, retry */ }

Prevention

When it happens

Trigger: Region partitioning (watershed/monotone/layer) producing fragmented regions that share an ID; aggressive contour simplification splitting one region into multiple outlines; thin region slivers.

Common situations: Very low minRegionArea allowing tiny regions; contour maxSimplificationError / maxEdgeLength interacting badly with complex geometry; watershed noise on nearly-planar scenes.

Related errors


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