包含用于 C# Job System 访问的网格数据的结构体。
使用 MeshData
结构体在 C# Job System 中访问、处理和创建网格。有两种类型的 MeshData
结构体:只读 MeshData
结构体,允许从 C# Job System 读取网格数据;可写 MeshData
结构体,允许您从 C# Job System 创建网格。
只读 MeshData
当您将一个或多个网格传递给 Mesh.AcquireReadOnlyMeshData 时,Unity 会返回一个包含只读 MeshData
结构体的 MeshDataArray。您可以从任何线程访问生成的 MeshDataArray
和 MeshData
结构体。出于内存跟踪和安全原因,创建 MeshDataArray
会产生一些开销,因此,最好只调用一次 Mesh.AcquireReadOnlyMeshData 并请求同一个 MeshDataArray
中的多个 MeshData
结构体,而不是多次调用 Mesh.AcquireReadOnlyMeshData。
每个 MeshData
结构体都包含给定网格的数据的只读快照。您可以使用 GetIndexData 和 GetVertexData 访问原始的只读网格数据,而无需任何内存分配、数据复制或格式转换。您需要了解确切的网格数据布局才能执行此操作:例如,所有网格顶点属性的存在和格式。您可以使用 GetColors、GetIndices、GetNormals、GetTangents、GetUVs 和 GetVertices 将只读网格数据复制到预先存在的数组中。这些方法还根据需要执行数据格式转换。例如,如果只读 MeshData
结构体使用 VertexAttributeFormat.Float16 法线,并且您调用 GetNormals,则法线将转换为目标数组中的 Vector3 法线。
完成对 MeshDataArray
的操作后,必须将其释放。只要您在修改网格之前释放了 MeshDataArray
,默认情况下,调用 Mesh.AcquireReadOnlyMeshData 不会导致任何内存分配或数据复制。但是,如果您调用 Mesh.AcquireReadOnlyMeshData,然后在 MeshDataArray
存在时修改网格,则 Unity 必须将 MeshDataArray
复制到新的内存分配中。此外,如果您调用 Mesh.AcquireReadOnlyMeshData,然后修改网格,则您的修改不会反映在 MeshData
结构体中。
使用 Dispose 释放 MeshDataArray
,或者使用 C# using
模式自动执行此操作。
using Unity.Collections; using UnityEngine; public class ExampleScript : MonoBehaviour { void Start() { var mesh = new Mesh(); mesh.vertices = new[] {Vector3.one, Vector3.zero}; using (var dataArray = Mesh.AcquireReadOnlyMeshData(mesh)) { var data = dataArray[0]; // prints "2" Debug.Log(data.vertexCount); var gotVertices = new NativeArray<Vector3>(mesh.vertexCount, Allocator.TempJob); data.GetVertices(gotVertices); // prints "(1.0, 1.0, 1.0)" and "(0.0, 0.0, 0.0)" foreach (var v in gotVertices) Debug.Log(v); gotVertices.Dispose(); } } }
可写 MeshData
使用 Mesh.AllocateWritableMeshData 获取一个包含可写 MeshData
结构体的 MeshDataArray。您可以从任何线程访问生成的 MeshDataArray
和 MeshData
结构体。出于内存跟踪和安全原因,创建 MeshDataArray
会产生一些开销,因此,最好只调用一次 Mesh.AllocateWritableMeshData 并请求同一个 MeshDataArray
中的多个 MeshData
结构体,而不是多次调用 Mesh.AllocateWritableMeshData。
您可以使用数据填充可写 MeshData
结构体以创建新的网格。使用 Mesh.MeshData.SetVertexBufferParams 设置顶点缓冲区大小和布局,然后写入 Mesh.MeshData.GetVertexData 返回的数组以设置顶点。使用 Mesh.MeshData.SetIndexBufferParams 设置索引缓冲区大小和格式,然后写入 Mesh.MeshData.GetIndexData 返回的数组以设置索引。写入 Mesh.MeshData.subMeshCount 以设置子网格的数量,然后使用 Mesh.MeshData.SetSubMesh 设置子网格数据。
使用数据填充可写 MeshData
结构体后,使用 Mesh.ApplyAndDisposeWritableMeshData 将数据应用于 Mesh 对象并自动释放 MeshDataArray
。
using UnityEngine; using UnityEngine.Rendering; using Unity.Collections;
[RequireComponent(typeof(MeshFilter))] public class ExampleScript : MonoBehaviour { void Start() { // Allocate mesh data for one mesh. var dataArray = Mesh.AllocateWritableMeshData(1); var data = dataArray[0];
// Tetrahedron vertices with positions and normals. // 4 faces with 3 unique vertices in each -- the faces // don't share the vertices since normals have to be // different for each face. data.SetVertexBufferParams(12, new VertexAttributeDescriptor(VertexAttribute.Position), new VertexAttributeDescriptor(VertexAttribute.Normal, stream: 1));
// Four tetrahedron vertex positions: var sqrt075 = Mathf.Sqrt(0.75f); var p0 = new Vector3(0, 0, 0); var p1 = new Vector3(1, 0, 0); var p2 = new Vector3(0.5f, 0, sqrt075); var p3 = new Vector3(0.5f, sqrt075, sqrt075 / 3);
// The first vertex buffer data stream is just positions; // fill them in. NativeArray<Vector3> pos = data.GetVertexData<Vector3>(); pos[0] = p0; pos[1] = p1; pos[2] = p2; pos[3] = p0; pos[4] = p2; pos[5] = p3; pos[6] = p2; pos[7] = p1; pos[8] = p3; pos[9] = p0; pos[10] = p3; pos[11] = p1;
// Note: normals will be calculated later in RecalculateNormals. // Tetrahedron index buffer: 4 triangles, 3 indices per triangle. // All vertices are unique so the index buffer is just a // 0,1,2,...,11 sequence. data.SetIndexBufferParams(12, IndexFormat.UInt16); NativeArray<ushort> indexBuffer = data.GetIndexData<ushort>(); for (ushort i = 0; i < indexBuffer.Length; ++i) indexBuffer[i] = i;
// One sub-mesh with all the indices. data.subMeshCount = 1; data.SetSubMesh(0, new SubMeshDescriptor(0, indexBuffer.Length)); // Create the mesh and apply data to it: var mesh = new Mesh(); mesh.name = "Tetrahedron"; Mesh.ApplyAndDisposeWritableMeshData(dataArray, mesh); mesh.RecalculateNormals(); mesh.RecalculateBounds(); GetComponent<MeshFilter>().mesh = mesh; } }
indexFormat | 获取 MeshData 中索引缓冲区数据的格式。(只读) |
subMeshCount | MeshData 中子网格的数量。 |
vertexBufferCount | 获取 MeshData 中顶点缓冲区的数量。(只读) |
vertexCount | 获取 MeshData 中顶点的数量。(只读) |
GetColors | 使用 MeshData 中的顶点颜色填充数组。 |
GetIndexData | 获取 MeshData 的索引缓冲区的原始数据。 |
GetIndices | 使用 MeshData 中给定子网格的索引填充数组。 |
GetNormals | 使用 MeshData 中的顶点法线填充数组。 |
GetSubMesh | 获取 MeshData 中给定子网格的数据。 |
GetTangents | 使用 MeshData 中的顶点切线填充数组。 |
GetUVs | 使用 MeshData 中的 UV 填充数组。 |
GetVertexAttributeDimension | 获取 MeshData 中给定顶点属性的维度。 |
GetVertexAttributeFormat | 获取 MeshData 中给定顶点属性的格式。 |
GetVertexAttributeOffset | 获取此 MeshData 上给定顶点数据属性在顶点缓冲区流中的偏移量。 |
GetVertexAttributeStream | 获取此 MeshData 上特定顶点数据属性的顶点缓冲区流索引。 |
GetVertexBufferStride | 获取顶点缓冲区流的跨度(以字节为单位)。 |
GetVertexData | 获取 MeshData 中给定顶点缓冲区流格式的原始数据。 |
GetVertices | 使用 MeshData 中的顶点位置填充数组。 |
HasVertexAttribute | 检查 MeshData 中是否存在给定的顶点属性。 |
SetIndexBufferParams | 设置 Unity 从 MeshData 创建的网格的索引缓冲区大小和格式。 |
SetSubMesh | 设置 Unity 从 MeshData 创建的网格的子网格的数据。 |
SetVertexBufferParams | 设置 Unity 从 MeshData 创建的网格的顶点缓冲区大小和布局。 |