Unity 动态创建Mesh 基础方法与高级方法

2024-03-01 1580阅读

温馨提示:这篇文章已超过411天没有更新,请注意相关的内容是否还可用!

最近在做项目优化,注意到动态创建Mesh时,Unity提供了一套高级方法用于快速创建模型,特此记录学习一下。

Unity 动态创建Mesh 基础方法与高级方法
(图片来源网络,侵删)

前言

关于Mesh的基本概念再次不在阐述,可以参考Unity Mesh 官方文档,介绍的很详细,其中

基础方法包括:SetVertices、SetNormals、SetUVs、SetTriangles、SetIndices、SetColors、SetTangents、SetBoneWeights

高级方法包括:SetVertexBufferParams、SetVertexBufferData、SetIndexBufferParams、SetIndexBufferData、SetSubMesh。

优势

  1. 使用基础方法有个限制,就是Mesh的最大顶点数量不能超过65535,而高级方法则没有这个限制。
  2. 高级方法跳过了一些检查,创建速度更快,尤其模型顶点数量较多的情况下,有性能提升,实测时间缩短将近1/3。

示例

基础方法

需要提前准备好模型的数据

属性名含义类型
vertices顶点坐标Verctor3[]
normals法线Verctor3[]
triangles顶点索引int[]
uv纹理坐标Verctor2[]
	//创建Mesh,并赋值,相当于调用SetVertices、SetNormals、SetTriangles、SetUVs
	Mesh mesh = new Mesh();
	mesh.vertices = myMeshes[i].vertices;
	mesh.normals = myMeshes[i].normals;
	mesh.triangles = myMeshes[i].triangles;
	mesh.uv = myMeshes[i].uv;
	
	//将Mesh赋值给MeshFilter组件
	GameObject gameObject = new GameObject();
	MeshFilter mf = gameObject.AddComponent();
	mf.sharedMesh = mesh;
	
	//给模型赋予材质
	MeshRenderer mr = gameObject.AddComponent();
	mr.material = material;

高级方法(推荐)

同上,先准备好模型的基础数据

	//
	//顶点属性描述中,添加该模型具有哪些属性,该例中有顶点、法线、一个uv,其中
	//顶点坐标  Position 用 3 个 Float32 数据表示
	//法线向量   Normal  用 3 个 Float32 数据表示
	//纹理坐标 TexCoord0 用 2 个 Float32 数据表示
	//
	VertexAttributeDescriptor[] vertexAttributes = new[]{
	    new VertexAttributeDescriptor(VertexAttribute.Position, VertexAttributeFormat.Float32, 3),
	    new VertexAttributeDescriptor(VertexAttribute.Normal, VertexAttributeFormat.Float32, 3),
	    new VertexAttributeDescriptor(VertexAttribute.TexCoord0, VertexAttributeFormat.Float32, 2)
	};
	
	//
	// 根据顶点数量创建缓冲区
	// 
	// 假设创建一个四方面片,则缓冲区数据如下
	//       顶点          法线           uv
	//    -5, -5,  0,    0, 0, -1,      0, 0,    //第 1 个顶点
	//    -5,  5,  0,    0, 0, -1,      0, 1,    //第 2 个顶点
	//     5, -5,  0,    0, 0, -1,      1, 0,    //第 3 个顶点
	//     5,  5,  0,    0, 0, -1,      1, 1     //第 4 个顶点
	//
	int vertexCount = myMeshes[i].vertices.Length;
	int bufferLength = 3 + 3 + 2;
	int vertexAttributeBufferLength = vertexCount * bufferLength;
	float[] vertexAttributeBuffer = new float[vertexAttributeBufferLength];
	
	//
	// 将准备好的模型数据填充到缓冲区
	//
	Vector3[] vertices = myMeshes[i].vertices;
	Vector3[] normals = myMeshes[i].normals;
	Vector2[] uv = myMeshes[i].uv;
	for (int j = 0; j  

注意!!!

      大家可以做一下测试,使用高级方法创建出来的Mesh,在Scene窗口旋转预览相机(或调整相机的size,在Game视图观察),当模型有三角面超过可视区域后,会突然消失不见!

      这是因为,使用高级方法创建出来的Mesh,由于跳过了Unity的检查,Mesh的Bounds信息缺失,这会导致一个现象,当模型的任意三角面不在相机的裁剪区域内时,模型会突然消失(被相机裁剪掉),因此需要调用RecalculateBounds方法计算一下模型的Bounds。

      基础方法创建出来的Mesh,Unity默认会对其进行Bounds计算(不需要调用RecalculateBounds方法),所以不会出现上述情况。

      因此可以推测,当修改了Mesh的顶点位置后,都需要调用一下RecalculateBounds方法,重新计算Bounds。

备注

此处为了展示高级方法的用法,因此未直接创建完整缓冲区数据,多执行一次数据的组装(即vertexAttributeBuffer数组)。实际应用时,会直接将缓冲区数据准备好(而不是分开存储vertices、normals、uv、triangles),直接调用SetXXXBufferParams、SetXXXBufferData。

参考:其他博主的文章Unity3D学习笔记4——创建Mesh高级接口

VPS购买请点击我

免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们,邮箱:ciyunidc@ciyunshuju.com。本站只作为美观性配图使用,无任何非法侵犯第三方意图,一切解释权归图片著作权方,本站不承担任何责任。如有恶意碰瓷者,必当奉陪到底严惩不贷!

目录[+]