You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity3D中如何最优分组两条曲线顶点生成平面网格三角形?

解决Unity中不等长平行曲线生成平面网格的问题

核心思路

因为两条曲线近乎平行且无交点,我们可以分两步处理,既保证所有顶点都被利用,又避免三角形重叠:

  1. 处理共同长度段:将两条曲线对应位置的相邻顶点组成四边形,再拆分为两个三角形,让网格贴合曲线的基础形状。
  2. 处理剩余顶点:如果其中一条曲线更长,将剩余的相邻顶点与另一条曲线的最后一个顶点连接成三角形,补全剩余区域。

关键细节

  • 顶点索引管理:先把第一条曲线的所有顶点存入mesh.vertices,再存入第二条曲线的顶点,这样第二条曲线的顶点索引 = 第一条曲线的顶点总数 + 自身在数组中的索引。
  • 三角形 winding 顺序:Unity默认顺时针索引的三角形为正面,代码中保持索引顺序为顺时针,避免背面被剔除。
  • 性能优化:用List<int>动态添加三角形索引,最后转成数组,避免预先分配过大的内存;所有三角形无重叠,减少绘制调用的性能开销。

完整代码示例

using UnityEngine;
using System.Collections.Generic;

public class CurveMeshGenerator : MonoBehaviour
{
    public List<Vector3> curveA; // 第一条曲线的顶点集合
    public List<Vector3> curveB; // 第二条曲线的顶点集合

    void Start()
    {
        GenerateMesh();
    }

    void GenerateMesh()
    {
        Mesh mesh = new Mesh();
        GetComponent<MeshFilter>().mesh = mesh;

        // 合并两条曲线的顶点到同一个数组
        List<Vector3> combinedVertices = new List<Vector3>();
        combinedVertices.AddRange(curveA);
        combinedVertices.AddRange(curveB);
        mesh.vertices = combinedVertices.ToArray();

        // 生成三角形索引数组
        List<int> triangles = new List<int>();
        int countA = curveA.Count;
        int countB = curveB.Count;

        // 先处理两条曲线长度重叠的部分
        int commonSegments = Mathf.Min(countA, countB) - 1;
        for (int k = 0; k < commonSegments; k++)
        {
            // 拆分四边形为第一个三角形:A[k] → A[k+1] → B[k+1]
            triangles.Add(k);
            triangles.Add(k + 1);
            triangles.Add(countA + k + 1);
            // 拆分四边形为第二个三角形:A[k] → B[k+1] → B[k]
            triangles.Add(k);
            triangles.Add(countA + k + 1);
            triangles.Add(countA + k);
        }

        // 处理长度较长的曲线剩余顶点
        if (countA > countB)
        {
            int lastBIdx = countA + countB - 1; // 第二条曲线最后一个顶点的索引
            for (int k = commonSegments; k < countA - 1; k++)
            {
                // 用第一条曲线的相邻顶点和第二条曲线的终点组成三角形
                triangles.Add(k);
                triangles.Add(k + 1);
                triangles.Add(lastBIdx);
            }
        }
        else if (countB > countA)
        {
            int lastAIdx = countA - 1; // 第一条曲线最后一个顶点的索引
            for (int k = commonSegments; k < countB - 1; k++)
            {
                // 用第一条曲线的终点和第二条曲线的相邻顶点组成三角形
                triangles.Add(lastAIdx);
                triangles.Add(countA + k);
                triangles.Add(countA + k + 1);
            }
        }

        mesh.triangles = triangles.ToArray();
        // 自动计算法线和包围盒(可选,根据需求调整)
        mesh.RecalculateNormals();
        mesh.RecalculateBounds();
    }
}

补充说明

如果曲线长度差异较大,想要更平滑的过渡效果,可以在较长的曲线上插入线性插值顶点,让两条曲线的顶点数一致,再用标准的四边形拆分法生成网格。另外,如果曲线的走向相反,可能需要调整三角形的索引顺序,保证正面朝向正确。

内容的提问来源于stack exchange,提问作者solidcomer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 19:56:13