egametang/ET · critical · Exception
rcBuildPolyMesh: Too many polygons {mesh.npolys} (max:{maxTr
Error message
rcBuildPolyMesh: Too many polygons {mesh.npolys} (max:{maxTris}). What it means
While storing polygons into the polymesh, rcBuildPolyMesh checks npolys against maxTris on every insert and throws once the pre-allocated polygon array is exceeded. maxTris is the sum of (contour.nverts - 2) over contours, so this trips when triangulation of the contours produces more polygons than the conservative estimate allowed for.
Source
Thrown at Packages/cn.etetet.recast/Scripts/Core/Share/Recast/RecastMesh.cs:1136
// Could not merge any polygons, stop.
break;
}
}
}
// Store polygons.
for (int j = 0; j < npolys; ++j)
{
int p = mesh.npolys * nvp * 2;
int q = j * nvp;
for (int k = 0; k < nvp; ++k)
mesh.polys[p + k] = polys[q + k];
mesh.regs[mesh.npolys] = cont.reg;
mesh.areas[mesh.npolys] = cont.area;
mesh.npolys++;
if (mesh.npolys > maxTris)
{
throw new Exception(
"rcBuildPolyMesh: Too many polygons " + mesh.npolys + " (max:" + maxTris + ").");
}
}
}
// Remove edge vertices.
for (int i = 0; i < mesh.nverts; ++i)
{
if (vflags[i] != 0)
{
if (!CanRemoveVertex(ctx, mesh, i))
continue;
RemoveVertex(ctx, mesh, i, maxTris);
// Remove vertex
// Note: mesh.nverts is already decremented inside RemoveVertex()!
// Fixup vertex flags
for (int j = i; j < mesh.nverts; ++j)
vflags[j] = vflags[j + 1];View on GitHub (pinned to 5cab01f7a8)
Solutions
- Increase rcConfig.maxVertsPerPoly (e.g. to 6, the Detour default) so large contours become fewer polygons.
- Lower the input contour density (raise cellSize, raise contour simplification tolerance via contourSimplificationError).
- Tile the world (set rcConfig.tileSize) so no single build exceeds the polygon budget.
- Audit that the contour set wasn't accidentally built with nvp lower than intended.
Example fix
// before: triangles only, explodes polygon count cfg.maxVertsPerPoly = 3; // after: allow convex polys up to 6 verts (Detour default) cfg.maxVertsPerPoly = 6;
Defensive patterns
Strategy: validation
Validate before calling
// Pre-check polygon budget using the same formula as the allocator
int maxTris = 0;
for (int i = 0; i < cset.conts.Count; i++)
if (cset.conts[i].nverts >= 3)
maxTris += cset.conts[i].nverts - 2;
if (maxTris > 0xfffe)
throw new InvalidOperationException($"rcBuildPolyMesh would exceed polygon budget: {maxTris}"); Prevention
- Use maxVertsPerPoly >= 6 (Detour default) to keep polygon counts down.
- Tile the world to bound per-tile polygon counts.
- Watch contourSimplificationError: too-low values inflate contour vertex counts.
When it happens
Trigger: The loop that converts simplified contour polygons into nvp-gons pushes mesh.npolys past maxTris. Happens when contours have many vertices and the per-contour (nverts-2) underestimate is collectively overrun, or when nvp (max verts per polygon) is small forcing many polygons.
Common situations: Setting rcConfig.maxVertsPerPoly low (e.g. 3 = pure triangles) on geometry with large contours; degenerate or very noisy contour sets from aggressive simplification settings; mismatched nvp between contour generation and polygon storage.
Related errors
- rcBuildPolyMesh: The resulting mesh has too many polygons {m
- rcBuildPolyMesh: Too many vertices {maxVertices}
- rcBuildPolyMesh: The resulting mesh has too many vertices {m
- addEdge: Too many edges ({edges.Count / 4}/{maxEdges}).
- rcBuildPolyMeshDetail: Shrinking triangle count from {ntris}
AI-assisted analysis of egametang/ET@5cab01f7a8 (2026-08-13).
Data as JSON: /api/errors/b6f0a7bd26d9ded9.
Report an issue: GitHub.