Unity 随附__平面__和__四边形__原始对象来代表平面(请参阅原始对象页面以了解更多详细信息)。然而,检查最小四边形网格的构造方式通常很有用,因为这可能是最简单的有用示例,只有四个顶点用于角和两个三角形。
第一件事是设置顶点数组。我们假设平面位于 X 和 Y 轴,并让其宽度和高度由参数变量确定。我们将按照左下角、右下角、左上角、右上角的顺序提供顶点。
var vertices = new Vector3[4]
{
new Vector3(0, 0, 0),
new Vector3(width, 0, 0),
new Vector3(0, height, 0),
new Vector3(width, height, 0)
};
mesh.vertices = vertices;
(由于网格数据属性在后台执行代码,因此一种高效得多的做法是在您自己的数组中设置数据,然后将其分配给属性,而不是逐个元素访问属性数组。)
接下来是三角形。由于我们需要两个三角形,每个三角形由三个整数定义,因此三角形数组总共有六个元素。注意对这些角排序时应用顺时针规则,左下方三角形将使用 0、2、1 作为其角索引,而右上方的三角形则使用 2、3、1。
var tris = new int[6]
{
// lower left triangle
0, 2, 1,
// upper right triangle
2, 3, 1
};
mesh.triangles = tris;
只有设置了顶点和三角形的网格才会在编辑器中可见,但看起来不太令人信服,因为它没有法线,未正确着色。平面的法线非常简单,它们全部都相同,并且在平面的局部空间中指向 Z 轴负方向。添加法线后,平面将得到正确着色,但是请记住,在场景中需要光照才能看到效果。
var normals = new Vector3[4]
{
-Vector3.forward,
-Vector3.forward,
-Vector3.forward,
-Vector3.forward
};
mesh.normals = normals;
最后,将纹理坐标添加到网格将使其能够正确显示材质。假设我们想要在整个平面上显示整个图像,UV 值将全部为 0 或 1(对应于纹理的角)。
var uv = new Vector2[4]
{
new Vector2(0, 0),
new Vector2(1, 0),
new Vector2(0, 1),
new Vector2(1, 1)
};
mesh.uv = uv;
完整脚本可能如下所示:
using UnityEngine;
public class CreateBillboard : MonoBehaviour
{
public float width = 1;
public float height = 1;
public void Start()
{
var mf = GetComponent<MeshFilter>();
var mesh = new Mesh();
mf.mesh = mesh;
var vertices = new Vector3[4]
{
new Vector3(0, 0, 0),
new Vector3(width, 0, 0),
new Vector3(0, height, 0),
new Vector3(width, height, 0)
};
mesh.vertices = vertices;
var tris = new int[6]
{
// lower left triangle
0, 2, 1,
// upper right triangle
2, 3, 1
};
mesh.triangles = tris;
var normals = new Vector3[4]
{
-Vector3.forward,
-Vector3.forward,
-Vector3.forward,
-Vector3.forward
};
mesh.normals = normals;
var uv = new Vector2[4]
{
new Vector2(0, 0),
new Vector2(1, 0),
new Vector2(0, 1),
new Vector2(1, 1)
};
mesh.uv = uv;
}
}
请注意,如果该代码在 Start 函数中执行一次,则网格将在整个游戏中保持不变。但是,您可以轻松地将此代码放入 Update 函数中,从而允许每帧都更改网格(但是这会显著增加 CPU 开销)。