Version: 2019.1
使用 Mesh 类
优化图形性能

示例 - 创建四边形

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 开销)。

使用 Mesh 类
优化图形性能