一、概述
Unity 的 Mesh 是用于表示三维物体的网格数据结构。它是由一系列顶点和三角形组成的网格,用于描述物体的形状和外观。
Mesh 是由顶点、三角形和其他相关信息组成的,它用于在 Unity 中创建和渲染三维对象。顶点是网格的基本构建单元,它们定义了物体的形状,每个顶点都有三维坐标和其他可选属性,如法线、 UV 坐标和颜色。三角形则是由三个顶点组成的,它们定义了网格表面的平面,形成了物体的可见表面。
Mesh 类提供了许多方法来操作顶点和三角形,例如添加、删除、移动顶点和三角形,以及调整网格的大小和形状。这些操作可以在 Unity 编辑器中进行,也可以在代码中通过使用 Unity 的 API 来实现。
使用 Mesh 可以创建各种类型的三维对象,如静态物体、动态物体、碰撞检测对象等。在 Unity 中,Mesh 还支持各种纹理和光照技术,以便更好地渲染物体的外观和效果。
在上一篇文章中,我介绍了 Unity 单个面 Mesh 的绘制方法,本章继续讲解 Mesh 多个面的绘制方法,参考:
Unity Mesh 生成图形(一)-CSDN博客
二、绘制立方体
Mesh 多个面的绘制,最简单的案例就是立方体了,在上一篇文章中,我用到的是 4 个顶点来绘制一个面,那个立方体 4 个面就是 8 个顶点了,先给这 8 个顶点用球型标记出来。
在场景中加入 8 个球,并给每个球设置一个颜色
对应的顶点是:
根据上图的序号,这 8 个球对应的位置是:
第1个球:0,0,0
第2个球:0,1,0
第3个球:1,0,0
第4个球:1,1,0
第5个球:1,0,1
第6个球:1,1,1
第7个球:0,0,1
第8个球:0,1,1
所以他们对应的顶点是:
//顶点坐标
Vector3[] vertices = new Vector3[]
{new Vector3(0, 0, 0),new Vector3(0, 1, 0),new Vector3(1, 0, 0),new Vector3(1, 1, 0),new Vector3(1, 0, 1),new Vector3(1, 1, 1),new Vector3(0, 0, 1),new Vector3(0, 1, 1),
};
虽然有了多个面,三角形的画法不变,唯一要改变的是顶点的下标,参考下图:
我们先来画第2个面试试
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Test4 : MonoBehaviour
{void Start(){GameObject obj = new GameObject();obj.name = "TestMesh";obj.transform.position = Vector3.zero;//网格渲染器MeshRenderer meshRenderer = obj.AddComponent<MeshRenderer>();meshRenderer.material = new Material(meshRenderer.material);//网格过滤器MeshFilter meshFilter = obj.AddComponent<MeshFilter>();//顶点坐标Vector3[] vertices = new Vector3[]{new Vector3(0, 0, 0),new Vector3(0, 1, 0),new Vector3(1, 0, 0),new Vector3(1, 1, 0),new Vector3(1, 0, 1),new Vector3(1, 1, 1),new Vector3(0, 0, 1),new Vector3(0, 1, 1),};//顶点下标顺序int[] triangles = new int[] { //第1个面//0, 1, 2, //2, 1, 3,//第二个面2, 3, 4,4, 3, 5,};//用列表数据创建网格 Mesh 对象Mesh mesh = new Mesh();mesh.name = "MestTest";//设置顶点mesh.SetVertices(vertices);//设置顶点索引mesh.triangles = triangles;// 自动计算法线mesh.RecalculateNormals();// 自动计算物体的整体边界mesh.RecalculateBounds();// 将mesh对象赋值给网格过滤器,就完成了meshFilter.mesh = mesh;}
}
由于 Unity 只渲染正面,摄像机的视角,默认指向这个渲染平面的背面,所以是看不到的,要转一下视角,效果:
知道了原理就很容易了,现在把四个面先画出来
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Test4 : MonoBehaviour
{void Start(){GameObject obj = new GameObject();obj.name = "TestMesh";obj.transform.position = Vector3.zero;//网格渲染器MeshRenderer meshRenderer = obj.AddComponent<MeshRenderer>();meshRenderer.material = new Material(meshRenderer.material);//网格过滤器MeshFilter meshFilter = obj.AddComponent<MeshFilter>();//顶点坐标Vector3[] vertices = new Vector3[]{new Vector3(0, 0, 0),new Vector3(0, 1, 0),new Vector3(1, 0, 0),new Vector3(1, 1, 0),new Vector3(1, 0, 1),new Vector3(1, 1, 1),new Vector3(0, 0, 1),new Vector3(0, 1, 1),};//顶点下标顺序int[] triangles = new int[] { //第1个面0, 1, 2,2, 1, 3,//第2个面2, 3, 4,4, 3, 5,//第3个面4, 5, 6,6, 5, 7,//第4个面6, 7, 0,0, 7, 1};//用列表数据创建网格 Mesh 对象Mesh mesh = new Mesh();mesh.name = "MestTest";//设置顶点mesh.SetVertices(vertices);//设置顶点索引mesh.triangles = triangles;// 自动计算法线mesh.RecalculateNormals();// 自动计算物体的整体边界mesh.RecalculateBounds();// 将mesh对象赋值给网格过滤器,就完成了meshFilter.mesh = mesh;}
}
效果:
由于后面两个面是背面,所以没渲染出来,只要把视角转到另一边,就可以看到了
现在把顶部和底部的面加上去吧
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Test4 : MonoBehaviour
{void Start(){GameObject obj = new GameObject();obj.name = "TestMesh";obj.transform.position = Vector3.zero;//网格渲染器MeshRenderer meshRenderer = obj.AddComponent<MeshRenderer>();meshRenderer.material = new Material(meshRenderer.material);//网格过滤器MeshFilter meshFilter = obj.AddComponent<MeshFilter>();//顶点坐标Vector3[] vertices = new Vector3[]{new Vector3(0, 0, 0),new Vector3(0, 1, 0),new Vector3(1, 0, 0),new Vector3(1, 1, 0),new Vector3(1, 0, 1),new Vector3(1, 1, 1),new Vector3(0, 0, 1),new Vector3(0, 1, 1),};//顶点下标顺序int[] triangles = new int[] { //第1个面0, 1, 2,2, 1, 3,//第2个面2, 3, 4,4, 3, 5,//第3个面4, 5, 6,6, 5, 7,//第4个面6, 7, 0,0, 7, 1,//顶部1, 7, 3,3, 7, 5,//底部6, 0, 4,4, 0, 2};//用列表数据创建网格 Mesh 对象Mesh mesh = new Mesh();mesh.name = "MestTest";//设置顶点mesh.SetVertices(vertices);//设置顶点索引mesh.triangles = triangles;// 自动计算法线mesh.RecalculateNormals();// 自动计算物体的整体边界mesh.RecalculateBounds();// 将mesh对象赋值给网格过滤器,就完成了meshFilter.mesh = mesh;}
}
底部由于需要反过来渲染,所以方向也要反着写,效果如下:
加上 着色线框 好像看的更清楚一些
但是立方体的光影好像有点问题,用 Unity 自带的 Cube 就没有这个问题。
下面创建一个立方体来看看 Unity 中的 Cube 有什么不同
添加一个脚本 Test5,并将其拖拽到 Cube 组件上
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Test5 : MonoBehaviour
{// Start is called before the first frame updatevoid Start(){MeshFilter meshFilter = GetComponent<MeshFilter>();if (meshFilter != null){Mesh mesh = meshFilter.sharedMesh;Debug.Log("Vertex Count: " + mesh.vertexCount);}}
}
运行:
可以看到,默认的 Cube 有 24 个顶点,而我生成的立方体只有 8 个顶点,关于光影的问题,在后面的文章中再来解决吧。
结束
如果这个帖子对你有所帮助,欢迎 关注 + 点赞 + 留言
end