在工作中有一个需求是需要一个可以用代码控制大小的圆锥,因为Unity引擎中自带的模型没有圆锥体,而且让建模的同学创建一个圆锥再控制顶点相比,直接代码生成一个圆锥体更加的快捷和便于修改。这里记录一下在完成这个需求时学习到的东西。
首先是我们在Unity中显示一个模型需要什么?我们在Unity中创建一个Cube,如下图所示,可以看到上面有两个组件是和模型的显示相关的,分包是Mesh Filter和Mesh Renderer。Mesh Filter包含了模型的网格数据,Mesh Renderer负责根据网格数据在引擎中将模型渲染出来并添加材质等效果。
可以看出模型的基本信息都在Mesh中,Mesh中有两个最关键的参数,分别是Mesh 的vertices和triangles。vertices中保存了所有顶点的位置数据,而triangles中保存了所有顶点的绘制顺序。什么意思呢?因为我们知道模型的面是有朝向的,也就是法线方向,如果法线方向朝向摄像机,那么这个面是可以被正常观测到的,如果法线方向背向摄像机那是看不到的。所以我们如果只知道模型的顶点数据是画不出模型的,因为我们不知道模型的面的朝向,所以在Mesh中用一组triangles数据记录了每个面的朝向。
那这个triangles数据是如何记录面的朝向呢?我们知道Unity中所用的模型一般都是三角面组成,所以在triangles记录了vertices数组的下标,他们3个3个的成一组,记录了如何将模型的面“绘制”出来,如果法线是朝向你的,这三个点将呈顺时针分布。我举个例子。
假设我们需要生成一个平面的模型,这个模型由两个三角面组成,那么它应该长这样:
我们假设以左下角的A点为原点 ,那么创建的vertices应该是:
Vector3[] vertices = new Vector3[]{
new Vector3(0,0,0),
new Vector3(0,1,0),
new Vector3(1,0,0),
new Vector3(1,1,0)
};
有这些顶点的位置还不够,我们需要在 triangles中记录法线的方向,如果要让法线朝向你,你需要以顺时针的顺序记录顶点。注意在triangles数组中我们记录的vertices数组元素的下标。
int[] triangles = new int[]{
0, 1, 2,
1, 3, 2
};
这里我们记录了平面中的两个三角形顶点连接的顺序,分别是vertices数组中的第0,1,2个元素和第1,3,2个元素,他们是顺时针记录的,所以当前得到的模型的法线是朝向我们的,如何这里记录的顺序是逆时针的,法线的朝向就行背对我们的。
最后附上代码和效果。
using UnityEngine;
[RequireComponent(typeof(MeshFilter))]
[RequireComponent(typeof(MeshRenderer))]
public class CreateMesh : MonoBehaviour {
public Material material;
private MeshFilter mf;
private MeshRenderer mr;
void Start()
{
mf = gameObject.GetComponent<MeshFilter>();
mr = gameObject.GetComponent<MeshRenderer>();
mr.materials[0] = material;
Mesh mesh = new Mesh();
mf.mesh = mesh;
//vertices记录mesh的顶点的位置
Vector3[] vertices = new Vector3[]{
new(0,0,0),
new(0,1,0),
new(1,0,0),
new(1,1,0)
};
//记录顶点绘制的顺序
int[] triangles = new int[]{
0, 1, 2,
2, 1, 3
};
mesh.vertices = vertices;
mesh.triangles = triangles;
mesh.RecalculateNormals();
}
}