egametang/ET · critical · Exception

rcBuildPolyMesh: Too many vertices {maxVertices}

Error message

rcBuildPolyMesh: Too many vertices {maxVertices}

What it means

rcBuildPolyMesh sums the vertex count across every contour in the input contour set before allocating the polymesh. Because internal indices pack into 16 bits, a combined vertex total of 0xfffe (65534) or more is rejected up front. The throw is a hard capacity guard at allocation time, before any polygon work begins.

Source

Thrown at Packages/cn.etetet.recast/Scripts/Core/Share/Recast/RecastMesh.cs:996

            mesh.borderSize = cset.borderSize;
            mesh.maxEdgeError = cset.maxError;

            int maxVertices = 0;
            int maxTris = 0;
            int maxVertsPerCont = 0;
            for (int i = 0; i < cset.conts.Count; ++i)
            {
                // Skip null contours.
                if (cset.conts[i].nverts < 3)
                    continue;
                maxVertices += cset.conts[i].nverts;
                maxTris += cset.conts[i].nverts - 2;
                maxVertsPerCont = Math.Max(maxVertsPerCont, cset.conts[i].nverts);
            }

            if (maxVertices >= 0xfffe)
            {
                throw new Exception("rcBuildPolyMesh: Too many vertices " + maxVertices);
            }

            int[] vflags = new int[maxVertices];

            mesh.verts = new int[maxVertices * 3];
            mesh.polys = new int[maxTris * nvp * 2];
            Array.Fill(mesh.polys, RC_MESH_NULL_IDX);
            mesh.regs = new int[maxTris];
            mesh.areas = new int[maxTris];

            mesh.nverts = 0;
            mesh.npolys = 0;
            mesh.nvp = nvp;
            mesh.maxpolys = maxTris;

            int[] nextVert = new int[maxVertices];

            int[] firstVert = new int[VERTEX_BUCKET_COUNT];

View on GitHub (pinned to 5cab01f7a8)

Solutions

  1. Reduce tile size so each tile's contour set has far fewer than 65534 vertices.
  2. Increase rcConfig.cellSize so each voxel covers more world area, shrinking contour vertex counts.
  3. Verify you passed a properly partitioned CompactHeightfield (use RC_PARTITION_WATERSHED or RC_PARTITION_MONOTONE) so large regions are split.
  4. If a deliberately large mesh is required, split the world into multiple Detour tiles and build a DtNavMesh from the tile set instead of one monolithic polymesh.

Example fix

// before: one giant tile
rcConfig cfg = new() { cellSize = 0.1f, tileSize = 0 };
// after: tile the world and cap per-tile vertex counts
rcConfig cfg = new() { cellSize = 0.2f, tileSize = 64 };
// build each tile separately, then assemble into DtNavMesh
Defensive patterns

Strategy: validation

Validate before calling

// Before calling rcBuildPolyMesh, sum contour vertices and reject early
int totalVerts = 0;
for (int i = 0; i < cset.conts.Count; i++)
    if (cset.conts[i].nverts >= 3)
        totalVerts += cset.conts[i].nverts;
if (totalVerts >= 0xfffe)
    throw new InvalidOperationException($"rcBuildPolyMesh input too large: {totalVerts} verts. Tile the world or raise cellSize.");

Prevention

When it happens

Trigger: Calling rcBuildPolyMesh(ctx, cset, nvp) where the sum of cset.conts[*].nverts over all non-null contours (nverts >= 3) reaches or exceeds 65534. This is driven purely by the input ContourSet density.

Common situations: Baking a single oversized navmesh tile from a very large or geometrically complex level; cellSize too small producing huge contour counts; merging many disjoint walkable regions into one tile; feeding un-partitioned geometry (no region/watershed partitioning) so contours stay enormous.

Related errors


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