Version: 2019.1
Using the Mesh Class
Оптимизация производительности графики

Пример - создание плоскости-биллборда

Для представления плоских поверхностей в Unity есть примитивы Plane и Quad (подробнее см. Примитивы. Однако полезно изучить то, как может быть построен минимальный меш плоскости, т.к. это, возможно, самой простой пример, с четырьмя вершинами для углов и двумя треугольниками.

В первую очередь, следует задать массив вершин. Предположим, что плоскость лежит на осях 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;

Т.к. свойства данных меша исполняют код “за кулисами”, будет куда более эффективно задать данные в собственном массиве, и затем назначить свойству, нежели получать доступ к свойству-массиву поэлементно.

Затем идут треугольники. Т.к. нам требуется 2 треугольника, каждый из которых определён тремя целыми числами, массив треугольников в общем счёте будет иметь 6 элементов. Помня о правиле упорядочивания углов по часовой стрелке, левый нижний треугольник будет использовать 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).

Using the Mesh Class
Оптимизация производительности графики