一个允许您创建或修改网格的类。
网格包含顶点和多个三角形数组。
从概念上讲,所有顶点数据都存储在相同大小的独立数组中。例如,如果您有一个包含 100 个顶点的网格,并且想要为每个顶点设置一个位置、法线和两个纹理坐标,那么该网格应该具有 vertices、normals、uv 和 uv2 数组,每个数组的大小均为 100。第 i 个顶点的数据位于每个数组中的索引“i”处。
对于每个顶点,可以存在顶点位置、法线、切线、颜色以及最多 8 个纹理坐标。纹理坐标最常为 2D 数据 (Vector2),但如果需要,它们也可以是 Vector3 或 Vector4。这最常用于在网格顶点中保存任意数据,以用于着色器中使用的特殊效果。对于蒙皮网格,顶点数据还可以包含 boneWeights。
网格面数据(即它所组成的三角形)只是每个三角形的三个顶点索引。例如,如果网格具有 10 个三角形,那么 triangles 数组应为 30 个数字,每个数字表示使用哪个顶点。triangles 数组中的前三个元素是构成该三角形的顶点索引;接下来的三个元素构成另一个三角形,依此类推。
请注意,虽然三角形网格是最常见的用例,但 Unity 还支持其他网格拓扑类型,例如线网格或点网格。对于线网格,每条线由两个顶点索引组成,依此类推。请参阅 SetIndices 和 MeshTopology。
简单 vs 高级网格 API
Mesh 类有两组方法用于从脚本将数据分配给网格。这组“简单”方法提供了用于设置索引、三角形、法线、切线等的基础。这些方法包括验证检查,例如确保您没有传入将包含超出边界索引的数据。它们代表了在 Unity 中从脚本分配网格数据的标准方法。
这些“简单”方法是:SetColors、SetIndices、SetNormals、SetTangents、SetTriangles、SetUVs、SetVertices、SetBoneWeights。
还有一组“高级”方法,这些方法允许您直接写入网格数据,并控制是否应执行任何检查或验证。这些方法适用于需要最大性能的高级用例。它们速度更快,但允许您跳过对所提供数据的检查。如果您使用这些方法,您必须确保没有提供无效数据,因为 Unity 不会为您检查。
这些“高级”方法是:SetVertexBufferParams、SetVertexBufferData、SetIndexBufferParams、SetIndexBufferData、SetSubMesh,并且您可以使用 MeshUpdateFlags 来控制执行或省略哪些检查或验证。使用 AcquireReadOnlyMeshData 获取网格数据的只读快照,您可以在 C# 作业和 Burst 中使用此快照,以及使用 AllocateWritableMeshData 与 ApplyAndDisposeWritableMeshData 从 C# 作业和 Burst 中创建网格。
从脚本操作网格
可能需要使用 Mesh API 来执行的三个常见任务
1. 从头开始构建网格:始终应按以下顺序进行
a) 分配 vertices
b) 分配 triangles。
using UnityEngine;
public class Example : MonoBehaviour { Vector3[] newVertices; Vector2[] newUV; int[] newTriangles;
void Start() { Mesh mesh = new Mesh(); GetComponent<MeshFilter>().mesh = mesh; mesh.vertices = newVertices; mesh.uv = newUV; mesh.triangles = newTriangles; } }
2. 每帧修改顶点属性:
a) 获取顶点
b) 修改它们
c) 将它们重新分配给网格。
using UnityEngine;
public class Example : MonoBehaviour { void Update() { Mesh mesh = GetComponent<MeshFilter>().mesh; Vector3[] vertices = mesh.vertices; Vector3[] normals = mesh.normals;
for (var i = 0; i < vertices.Length; i++) { vertices[i] += normals[i] * Mathf.Sin(Time.time); }
mesh.vertices = vertices; } }
3. 持续更改网格三角形和顶点:
a) 调用 Clear 以从头开始
b) 分配顶点和其他属性
c) 分配三角形索引。
在分配新顶点或三角形之前,务必调用 Clear。Unity 始终检查提供的三角形索引,以确保它们不会引用超出边界的顶点。调用 Clear 然后分配顶点再分配三角形,可以确保您永远不会拥有超出边界的數據。
using UnityEngine;
public class ExampleClass : MonoBehaviour { Vector3[] newVertices; Vector2[] newUV; int[] newTriangles;
void Start() { Mesh mesh = GetComponent<MeshFilter>().mesh;
mesh.Clear();
// Do some calculations... mesh.vertices = newVertices; mesh.uv = newUV; mesh.triangles = newTriangles; } }
bindposeCount | 网格中绑定姿势的数量。 |
bindposes | 绑定姿势。每个索引处的绑定姿势都引用具有相同索引的骨骼。 |
blendShapeCount | 返回此网格上的混合形状数量。 |
boneWeights | 网格中每个顶点的骨骼权重,每个顶点代表 4 个骨骼。 |
bounds | 网格的边界体积。 |
colors | 网格的顶点颜色。 |
colors32 | 网格的顶点颜色。 |
indexBufferTarget | 网格 GPU 索引缓冲区的预期目标用途。 |
indexFormat | 网格索引缓冲区数据的格式。 |
isReadable | 如果网格启用了读写,则返回 true;如果网格未启用读写,则返回 false。 |
normals | 网格的法线。 |
skinWeightBufferLayout | 骨骼权重缓冲区中数据的维度。 |
subMeshCount | Mesh 对象内部子网格的数量。 |
tangents | 网格的切线。 |
triangles | 包含网格中所有三角形的数组。 |
uv | 第一个通道中的纹理坐标 (UV)。 |
uv2 | 第二个通道中的纹理坐标 (UV)。 |
uv3 | 第三个通道中的纹理坐标 (UV)。 |
uv4 | 第四个通道中的纹理坐标 (UV)。 |
uv5 | 第五个通道中的纹理坐标 (UV)。 |
uv6 | 第六个通道中的纹理坐标 (UV)。 |
uv7 | 第七个通道中的纹理坐标 (UV)。 |
uv8 | 第八个通道中的纹理坐标 (UV)。 |
vertexAttributeCount | 返回网格具有的顶点属性数量。(只读) |
vertexBufferCount | 获取网格中存在的顶点缓冲区数量。(只读) |
vertexBufferTarget | 网格 GPU 顶点缓冲区的预期目标用途。 |
vertexCount | 返回网格中的顶点数量(只读)。 |
vertices | 返回顶点位置的副本或分配新的顶点位置数组。 |
Mesh | 创建一个空网格。 |
AddBlendShapeFrame | 添加新的混合形状帧。 |
Clear | 清除所有顶点数据和所有三角形索引。 |
ClearBlendShapes | 从网格中清除所有混合形状。 |
CombineMeshes | 将多个网格组合到此网格中。 |
GetAllBoneWeights | 获取网格的骨骼权重。 |
GetBaseVertex | 获取给定子网格的基顶点索引。 |
GetBindposes | 获取网格的绑定姿势。 |
GetBlendShapeBuffer | 检索一个 GraphicsBuffer,该缓冲区提供对 GPU 混合形状顶点数据的直接读写访问。 |
GetBlendShapeBufferRange | 获取给定混合形状的混合形状顶点数据的地址。 |
GetBlendShapeFrameCount | 返回混合形状的帧数量。 |
GetBlendShapeFrameVertices | 检索混合形状帧的 deltaVertices、deltaNormals 和 deltaTangents。 |
GetBlendShapeFrameWeight | 返回混合形状帧的权重。 |
GetBlendShapeIndex | 通过给定名称返回混合形状的索引。 |
GetBlendShapeName | 通过给定索引返回混合形状的名称。 |
GetBonesPerVertex | 每个顶点的非零骨骼权重数量。 |
GetBoneWeightBuffer | 检索一个 GraphicsBuffer,该缓冲区提供对 GPU 骨骼权重数据的直接读写访问。 |
GetBoneWeights | 获取网格的骨骼权重。 |
GetColors | 获取网格的顶点颜色。 |
GetIndexBuffer | 检索指向 GPU 索引缓冲区的 GraphicsBuffer。 |
GetIndexCount | 获取给定子网格的索引数量。 |
GetIndexStart | 获取网格索引缓冲区内给定子网格的起始索引位置。 |
GetIndices | 获取指定子网格的索引列表。 |
GetNativeIndexBufferPtr | 检索指向索引缓冲区的本机(底层图形 API)指针。 |
GetNativeVertexBufferPtr | 检索指向顶点缓冲区的本机(底层图形 API)指针。 |
GetNormals | 获取网格的顶点法线。 |
GetSubMesh | 获取有关网格的子网格的信息。 |
GetTangents | 获取网格的切线。 |
GetTopology | 获取子网格的拓扑。 |
GetTriangles | 获取此对象上指定子网格的三角形列表。 |
GetUVDistributionMetric | UV 分布度量可用于根据摄像机的位置计算所需的mipmap 级别。 |
GetUVs | 获取存储在给定通道中的纹理坐标 (UV)。 |
GetVertexAttribute | 根据其索引返回有关顶点属性的信息。 |
GetVertexAttributeDimension | 获取此网格上特定顶点数据属性的维度。 |
GetVertexAttributeFormat | 获取此网格上特定顶点数据属性的格式。 |
GetVertexAttributeOffset | 获取此网格上特定顶点数据属性在顶点缓冲区流中的偏移量。 |
GetVertexAttributes | 获取有关网格顶点属性的信息。 |
GetVertexAttributeStream | 获取此网格上特定顶点数据属性的顶点缓冲区流索引。 |
GetVertexBuffer | 检索一个 GraphicsBuffer,该缓冲区提供对 GPU 顶点缓冲区的直接访问。 |
GetVertexBufferStride | 获取顶点缓冲区流的跨度(以字节为单位)。 |
GetVertices | 获取网格的顶点位置。 |
HasVertexAttribute | 检查此网格上是否存在特定顶点数据属性。 |
MarkDynamic | 优化网格以进行频繁更新。 |
MarkModified | 通知渲染器组件网格几何图形已更改。 |
Optimize | 优化网格数据以提高渲染性能。 |
OptimizeIndexBuffers | 优化网格的几何图形以提高渲染性能。 |
OptimizeReorderVertexBuffer | 优化网格顶点以提高渲染性能。 |
重新计算边界 | 使用顶点数据重新计算网格及其所有子网格的包围盒。 |
重新计算法线 | 从三角形和顶点重新计算网格的法线。 |
重新计算切线 | 从法线和纹理坐标重新计算网格的切线。 |
重新计算 UV 分布度量 | 从顶点和 UV 坐标重新计算网格的 UV 分布度量。 |
重新计算 UV 分布度量 | 从顶点和 UV 坐标重新计算网格的 UV 分布度量。 |
设置绑定姿势 | 设置网格的绑定姿势。 |
设置骨骼权重 | 设置网格的骨骼权重。 |
设置颜色 | 设置网格的每个顶点颜色。 |
设置索引缓冲区数据 | 设置网格索引缓冲区的数据。 |
设置索引缓冲区参数 | 设置索引缓冲区大小和格式。 |
设置索引 | 设置子网格的索引缓冲区。 |
设置法线 | 设置网格的法线。 |
设置子网格 | 设置网格子网格的信息。 |
设置子网格 | 设置定义此网格中所有子网格的信息,替换任何现有子网格。 |
设置切线 | 设置网格的切线。 |
设置三角形 | 设置子网格的三角形列表。 |
设置 UV | 设置存储在给定通道中的纹理坐标 (UV)。 |
设置顶点缓冲区数据 | 设置网格顶点缓冲区的数据。 |
设置顶点缓冲区参数 | 设置顶点缓冲区大小和布局。 |
设置顶点 | 分配新的顶点位置数组。 |
上传网格数据 | 将之前完成的网格修改上传到图形 API。 |
获取只读网格数据 | 获取网格数据的快照以供只读访问。 |
分配可写网格数据 | 使用 C# 作业分配用于网格创建的数据结构。 |
应用并处置可写网格数据 | 将 MeshData 结构中定义的数据应用于 Mesh 对象。 |
GetInstanceID | 获取对象的实例 ID。 |
ToString | 返回对象的名称。 |
Destroy | 删除游戏对象、组件或资产。 |
DestroyImmediate | 立即销毁对象 obj。强烈建议使用 Destroy 代替。 |
DontDestroyOnLoad | 在加载新场景时不要销毁目标对象。 |
FindAnyObjectByType | 检索任何已加载的活动对象类型。 |
FindFirstObjectByType | 检索第一个已加载的活动对象类型。 |
FindObjectsByType | 检索所有已加载的对象类型列表。 |
Instantiate | 克隆对象 original 并返回克隆。 |
InstantiateAsync | 捕获原始对象的快照(该对象必须与某个游戏对象相关)并返回 AsyncInstantiateOperation。 |
bool | 对象是否存在? |
operator != | 比较两个对象是否引用不同的对象。 |
operator == | 比较两个对象引用是否引用同一个对象。 |