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

生成并显示数千个多边形的最佳实践及性能优化技术问询

嘿,我完全懂你的痛点——实例化上千个带Mesh的对象在低配设备上确实会吃爆性能,毕竟每个实例都要占用独立的Draw Call和内存资源,尤其是手机这类资源有限的设备。既然这些都是静态多边形,咱们有几个高效的解决方案,其中Shader驱动的方案是最适合的,我给你一步步拆解,从省心的官方方案到极致性能的自定义实现:

方案一:GPU Instancing(最省心,几乎不用写自定义Shader)

这是Unity官方提供的批量渲染方案,专门针对大量重复对象的场景,完全适配你的静态多边形需求:

  • 第一步:配置资源
    把你的单个多边形Mesh做成Prefab,打开Prefab的Mesh Renderer面板,勾选Enable GPU Instancing选项。然后用Unity内置的Shader(比如Universal Render Pipeline/Lit或者Standard),这些Shader默认已经支持GPU Instancing。
  • 第二步:批量渲染代码
    不要一个个Instantiate对象,而是用Graphics.DrawMeshInstanced一次性把所有多边形渲染出来。你只需要提前准备好每个多边形的位置/旋转/缩放矩阵,以及颜色数组:
    public Mesh polygonMesh;
    public Material instancedMaterial;
    private Matrix4x4[] _instanceMatrices;
    private Color[] _instanceColors;
    private int _polygonCount = 10000;
    
    void Start()
    {
        // 提前初始化所有实例的数据(静态对象只需初始化一次)
        _instanceMatrices = new Matrix4x4[_polygonCount];
        _instanceColors = new Color[_polygonCount];
        
        for (int i = 0; i < _polygonCount; i++)
        {
            // 随机生成示例位置,你可以替换成自己的坐标数据
            Vector3 pos = new Vector3(Random.Range(-20, 20), Random.Range(-20, 20), 0);
            _instanceMatrices[i] = Matrix4x4.TRS(pos, Quaternion.Euler(0, 0, Random.Range(0, 360)), Vector3.one);
            _instanceColors[i] = new Color(Random.value, Random.value, Random.value);
        }
    
        // 把颜色设为实例化属性,让每个多边形能单独改色
        instancedMaterial.SetColorArray("_BaseColor", _instanceColors);
    }
    
    void Update()
    {
        // 一次性渲染所有实例,仅需1个Draw Call
        Graphics.DrawMeshInstanced(polygonMesh, 0, instancedMaterial, _instanceMatrices, _polygonCount);
    }
    
  • 颜色修改技巧:如果后期需要修改部分多边形的颜色,只需更新_instanceColors数组,再调用instancedMaterial.SetColorArray("_BaseColor", _instanceColors)即可,静态场景下尽量少做动态修改,性能会更好。
方案二:自定义Shader + Compute Buffer(极致性能,适合超大量多边形)

如果GPU Instancing还满足不了你的需求(比如数万个甚至数十万个多边形),可以用Compute Buffer把所有多边形的参数传到GPU,让Shader直接生成顶点并渲染,全程只有1个Draw Call:

  • 第一步:定义数据结构
    不用存每个多边形的所有顶点,而是用更轻量化的参数(中心位置、尺寸、旋转、颜色)来推导顶点,节省内存:
    public struct PolygonData
    {
        public Vector3 center;
        public Vector2 size;
        public float rotation;
        public Color color;
    }
    
  • 第二步:初始化Compute Buffer
    把所有多边形的数据传到GPU的Buffer中:
    public ComputeBuffer _polygonBuffer;
    public Material _polygonMaterial;
    private int _polygonCount = 50000;
    
    void Start()
    {
        PolygonData[] polygons = new PolygonData[_polygonCount];
        for (int i = 0; i < _polygonCount; i++)
        {
            polygons[i] = new PolygonData
            {
                center = new Vector3(Random.Range(-30, 30), Random.Range(-30, 30), 0),
                size = new Vector2(Random.Range(0.5f, 2f), Random.Range(0.5f, 2f)),
                rotation = Random.Range(0, Mathf.PI * 2),
                color = new Color(Random.value, Random.value, Random.value)
            };
        }
    
        // 创建GPU Buffer,传入数据大小和数量
        _polygonBuffer = new ComputeBuffer(_polygonCount, System.Runtime.InteropServices.Marshal.SizeOf(typeof(PolygonData)));
        _polygonBuffer.SetData(polygons);
        // 把Buffer传给Shader
        _polygonMaterial.SetBuffer("_PolygonBuffer", _polygonBuffer);
    }
    
    void OnDestroy()
    {
        // 必须释放Buffer,避免内存泄漏
        if (_polygonBuffer != null) _polygonBuffer.Release();
    }
    
    void OnRenderObject()
    {
        // 激活Shader Pass,调用GPU渲染所有多边形
        _polygonMaterial.SetPass(0);
        // 按四边形拓扑渲染,每个多边形占4个顶点
        Graphics.DrawProcedural(MeshTopology.Quads, _polygonCount * 4);
    }
    
  • 第三步:编写自定义Shader(URP版本)
    这个Shader会读取Compute Buffer里的参数,实时生成每个多边形的顶点并上色:
    Shader "Custom/ProceduralStaticPolygons"
    {
        SubShader
        {
            Tags { "RenderType"="Opaque" "RenderPipeline"="UniversalPipeline" }
            LOD 100
    
            Pass
            {
                CGPROGRAM
                #pragma vertex vert
                #pragma fragment frag
    
                #include "UnityCG.cginc"
                #include "UnityURP.cginc"
    
                // 和C#端对应的数据结构
                struct PolygonData
                {
                    float3 center;
                    float2 size;
                    float rotation;
                    float4 color;
                };
    
                // GPU端的Buffer
                StructuredBuffer<PolygonData> _PolygonBuffer;
    
                struct appdata
                {
                    uint vertexID : SV_VertexID;
                    uint instanceID : SV_InstanceID;
                };
    
                struct v2f
                {
                    float4 vertex : SV_POSITION;
                    float4 color : COLOR;
                };
    
                v2f vert (appdata v)
                {
                    v2f o;
                    // 获取当前实例的多边形数据
                    PolygonData poly = _PolygonBuffer[v.instanceID];
                    
                    // 生成四边形的四个本地顶点坐标
                    float2 uv = float2(v.vertexID % 2, v.vertexID / 2) * 2 - 1;
                    // 应用旋转
                    float rotSin = sin(poly.rotation);
                    float rotCos = cos(poly.rotation);
                    float2 rotatedUV = float2(uv.x * rotCos - uv.y * rotSin, uv.x * rotSin + uv.y * rotCos);
                    
                    // 计算世界空间位置并转成裁剪空间
                    float3 worldPos = poly.center + float3(rotatedUV * poly.size * 0.5, 0);
                    o.vertex = TransformWorldToHClip(worldPos);
                    o.color = poly.color;
                    
                    return o;
                }
    
                float4 frag (v2f i) : SV_Target
                {
                    return i.color;
                }
                ENDCG
            }
        }
    }
    
  • 适配三角形多边形:如果你的多边形是三角形,只需把MeshTopology.Quads改成MeshTopology.Triangles,每个实例对应3个顶点即可。
额外小贴士
  • 静态对象的所有数据尽量在Start里一次性初始化,不要每帧更新,能最大化性能。
  • 如果需要修改颜色,只需更新C#端的PolygonData数组,再调用_polygonBuffer.SetData(polygons)即可,静态场景下尽量减少动态修改次数。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 10:18:29