egametang/ET · critical · Exception

addEdge: Too many edges ({edges.Count / 4}/{maxEdges}).

Error message

addEdge: Too many edges ({edges.Count / 4}/{maxEdges}).

What it means

AddEdge in the detail mesh builder maintains a flat int-list of edges (4 ints per edge: s, t, left, right) and rejects adding a new edge once edges.Count/4 >= maxEdges. This bounds detail triangulation memory and is a hard cap on the half-edge structure used by Delaunay triangulation.

Source

Thrown at Packages/cn.etetet.recast/Scripts/Core/Share/Recast/RecastMeshDetail.cs:449

        private static int FindEdge(List<int> edges, int s, int t)
        {
            for (int i = 0; i < edges.Count / 4; i++)
            {
                int e = i * 4;
                if ((edges[e + 0] == s && edges[e + 1] == t) || (edges[e + 0] == t && edges[e + 1] == s))
                {
                    return i;
                }
            }

            return EV_UNDEF;
        }

        private static void AddEdge(RcTelemetry ctx, List<int> edges, int maxEdges, int s, int t, int l, int r)
        {
            if (edges.Count / 4 >= maxEdges)
            {
                throw new Exception("addEdge: Too many edges (" + edges.Count / 4 + "/" + maxEdges + ").");
            }

            // Add edge if not already in the triangulation.
            int e = FindEdge(edges, s, t);
            if (e == EV_UNDEF)
            {
                edges.Add(s);
                edges.Add(t);
                edges.Add(l);
                edges.Add(r);
            }
        }

        private static void UpdateLeftFace(List<int> edges, int e, int s, int t, int f)
        {
            if (edges[e + 0] == s && edges[e + 1] == t && edges[e + 2] == EV_UNDEF)
            {
                edges[e + 2] = f;

View on GitHub (pinned to 5cab01f7a8)

Solutions

  1. Reduce rcConfig.detailSampleDist (set larger, or 0 to disable internal sampling) to lower edge count.
  2. Reduce rcConfig.detailSampleMaxError to require fewer detail subdivisions.
  3. Coarsen the base polymesh (larger cellSize) so individual polygons are smaller and need fewer detail edges.
  4. If you intentionally need high detail, confirm the maxEdges budget in DelaunayHull scales with your expected vertex count.

Example fix

// before: dense detail sampling
cfg.detailSampleDist = 0.5f;
cfg.detailSampleMaxError = 0.5f;
// after: relax detail sampling
cfg.detailSampleDist = 6f;   // larger = fewer samples
cfg.detailSampleMaxError = 1f;
Defensive patterns

Strategy: validation

Validate before calling

// Sanity-check detail config before building detail
if (cfg.detailSampleDist > 0 && cfg.detailSampleDist < cfg.cellSize)
    Log.Warning("detailSampleDist smaller than cellSize may exceed edge budget on large polys");

Prevention

When it happens

Trigger: DelaunayHull / detail mesh generation calls AddEdge when the edge count reaches the caller-supplied maxEdges. maxEdges is computed from the detail input size (typically maxVertexCount squared budget). Trips when a polygon requires more unique edges than the budget permits.

Common situations: Detail mesh build (rcBuildPolyMeshDetail) on a polygon with very many internal sample points (large sampleDist budget on a large poly); high detail sample density (small sampleDist) creating many edges; degenerate input geometry producing excessive triangulation edges.

Related errors


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