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

GraphicsBuffer的GetData始终返回全0数组问题排查

问题

目标Mesh的Read/Write选项为false且无法修改,尝试用GraphicsBuffer克隆Mesh:测试项目中代码运行正常,但主项目里sourceDataBuffer.GetData(sourceData)和sourceIndexBuffer.GetData(sourceIndex)返回全0数组。该问题仅在包含不可读Mesh的资源包中出现,原以为GraphicsBuffer适配此类Mesh,实际不行,请问原因是什么?

测试代码

public static bool Run(Mesh sourceMesh, out Mesh generatedMesh)
{
    GraphicsBuffer sourceDataBuffer = sourceMesh.GetVertexBuffer(0);
    GraphicsBuffer sourceIndexBuffer = sourceMesh.GetIndexBuffer();

    var vertexCount = sourceDataBuffer.count;
    var indexCount = sourceIndexBuffer.count;

    byte[] sourceData = new byte[vertexCount * (sourceDataBuffer.stride / sizeof(byte))];
    byte[] sourceIndex = new byte[(int)(indexCount * ((float)sourceIndexBuffer.stride / sizeof(byte)))];

    sourceDataBuffer.GetData(sourceData);
    sourceIndexBuffer.GetData(sourceIndex);

    var attributes = sourceMesh.GetVertexAttributes();

    generatedMesh = new Mesh();
    generatedMesh.vertexBufferTarget |= GraphicsBuffer.Target.Raw;

    generatedMesh.SetVertexBufferParams(vertexCount, attributes);
    generatedMesh.SetVertexBufferData(sourceData, 0, 0, sourceData.Length);
    generatedMesh.SetIndexBufferParams(indexCount, sourceMesh.indexFormat);
    generatedMesh.SetIndexBufferData(sourceIndex, 0, 0, sourceIndex.Length);

    generatedMesh.subMeshCount = sourceMesh.subMeshCount;
    for (int i = 0; i < sourceMesh.subMeshCount; i++)
    {
        var subMeshDescriptor = sourceMesh.GetSubMesh(i);
        generatedMesh.SetSubMesh(i, subMeshDescriptor);
    }

    sourceDataBuffer.Release();
    sourceIndexBuffer.Release();

    generatedMesh.RecalculateBounds();

    return true; // No error
}
原因分析与解决方案

核心原因

  • 资源包GPU优化限制:主项目资源包中的Mesh大概率开启了GPU-only内存优化,这类Mesh的顶点/索引数据仅存储在GPU显存中,没有保留CPU可访问的副本。测试项目中的Mesh未经过该优化,所以GraphicsBuffer能正常读取数据;而资源包构建时的优化逻辑会移除CPU访问权限,导致GetData无法从显存拉取数据,只能返回全0数组。
  • GraphicsBuffer权限缺失:当Mesh的Read/Write为false时,通过GetVertexBuffer/GetIndexBuffer获取的GraphicsBuffer默认没有CPU读取权限。测试环境中Mesh可能因未打包而隐式保留了权限,资源包构建时则严格移除了该权限,导致读取操作无效。

解决办法

  1. 调整资源包构建设置:在资源包构建窗口中,关闭Mesh的Optimize Mesh Data选项,或勾选Keep CPU Data(不同Unity版本选项名称略有差异),确保Mesh数据保留CPU可访问的副本。
  2. 改用官方只读数据API:使用Unity提供的Mesh.AcquireReadOnlyMeshData接口,专门用于读取不可读Mesh的数据,不受Read/Write选项限制,替换原有GraphicsBuffer读取逻辑:
    using (var dataArray = Mesh.AcquireReadOnlyMeshData(sourceMesh))
    {
        var meshData = dataArray[0];
        // 读取顶点数据示例
        Vector3[] vertices = new Vector3[meshData.vertexCount];
        meshData.GetVertices(vertices);
        // 读取索引数据示例
        int[] indices = new int[meshData.indexCount];
        meshData.GetIndices(indices, 0);
        // 后续构建新Mesh的逻辑,改用这些读取到的数据填充即可
    }
    
  3. 放弃GraphicsBuffer直接读取:对于不可读Mesh,GraphicsBuffer的CPU访问权限依赖资源构建配置,稳定性远低于官方只读API,优先使用Mesh.AcquireReadOnlyMeshData更可靠。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 07:45:48