Unity - Улучшите генерацию сетки и производительность рендеринга

Так как я только недавно начал изучать сетки, как они работают, что они делают и так далее, я решил использовать свои собственные расчеты для создания сетки круга. К сожалению, это действительно очень медленно!

Поэтому я ищу советы по улучшению, чтобы сделать его медленным (потому что это, вероятно, лучшее, что он получит...)

Вот код, который я использую для создания круга:

public static void createCircle(MeshFilter meshFilter, float innerRadius, float outerRadius, Color color, float xPosition = 0, float yPosition = 0, float startDegree = 0, float endDegree = 360, int points = 100)
         {
             Mesh mesh = meshFilter.mesh;
             mesh.Clear();

             //These values will result in no (or very ugly in the case of points < 10) circle, so let's safe calculation and just return an empty mesh!
             if (startDegree == endDegree || points < 10 || innerRadius >= outerRadius || innerRadius < 0 || outerRadius <= 0)
             {
                 return;
             }

             //The points for the full circle shall be whatever is given but if its not the full circle we dont need all the points!
             points = (int)(Mathf.Abs(endDegree - startDegree) / 360f * points);

             //We always need an uneven number of points!
             if (points % 2 != 0) { points++; }

             Vector3[] vertices = new Vector3[points];
             float degreeStepSize = (endDegree - startDegree) * 2 / (points - 3);
             float halfRadStepSize = (degreeStepSize) * Mathf.Deg2Rad / 2f;
             float startRad = Mathf.Deg2Rad * startDegree;
             float endRad = Mathf.Deg2Rad * endDegree;

             //Let's save the vector at the beginning and the one on the end to make a perfectly straight line
             vertices[0] = new Vector3(Mathf.Sin(startRad) * outerRadius + xPosition, Mathf.Cos(startRad) * outerRadius + yPosition, 0);
             vertices[vertices.Length - 1] = new Vector3(Mathf.Sin(endRad) * innerRadius + xPosition, Mathf.Cos(endRad) * innerRadius + yPosition, 0);

             for (int i = 1; i < vertices.Length - 1; i++)
             {
                 //Pure coinsidence that saved some calculatons. Half Step Size is the same as what would needed to be calculated here!
                 float rad = (i - 1) * halfRadStepSize + startRad;
                 if (i % 2 == 0)
                 {
                     vertices[i] = new Vector3(Mathf.Sin(rad) * outerRadius + xPosition, Mathf.Cos(rad) * outerRadius + yPosition, 0);
                 }
                 else
                 {
                     vertices[i] = new Vector3(Mathf.Sin(rad) * innerRadius + xPosition, Mathf.Cos(rad) * innerRadius + yPosition, 0);
                 }
             }
             mesh.vertices = vertices;

             int[] tri = new int[(vertices.Length - 2) * 3];
             for (int i = 0; i < (vertices.Length - 2); i++)
             {
                 int index = i * 3;
                 if (i % 2 == 0)
                 {
                     tri[index + 0] = i + 0;
                     tri[index + 1] = i + 2;
                     tri[index + 2] = i + 1;
                 }
                 else
                 {
                     tri[index + 0] = i + 0;
                     tri[index + 1] = i + 1;
                     tri[index + 2] = i + 2;
                 }
             }

             mesh.triangles = tri;
             Vector3[] normals = new Vector3[vertices.Length];
             Color[] colors = new Color[vertices.Length];
             for (int i = 0; i < vertices.Length; i++)
             {
                 normals[i] = Vector3.forward;
                 colors[i] = color;
             }
             mesh.normals = normals;
             mesh.colors = colors;

             meshFilter.mesh = mesh;
         }

Я знаю, что "мог бы просто использовать LineRenderer, поставляемый с Unity, это быстрее, чем все, что вы когда-либо будете писать", но здесь дело не в этом. Я пытаюсь понять меши и посмотреть, где я могу настроить свой код, чтобы улучшить его производительность.

Заранее спасибо за помощь!

1 ответ

Вы можете почти удвоить скорость, удалив дополнительное выделение памяти. Поскольку Vector3 является типом значения, они уже выделяются при выделении массива. Vector3.forward также каждый раз выделяет новый Vector3, и мы можем использовать его повторно.

public static void createCircle(MeshFilter meshFilter, float innerRadius, float outerRadius, Color color, float xPosition = 0, float yPosition = 0, float startDegree = 0, float endDegree = 360, int points = 100)
 {
     Mesh mesh = meshFilter.mesh;
     mesh.Clear();

     //These values will result in no (or very ugly in the case of points < 10) circle, so let's safe calculation and just return an empty mesh!
     if (startDegree == endDegree || points < 10 || innerRadius >= outerRadius || innerRadius < 0 || outerRadius <= 0)
     {
         return;
     }

     //The points for the full circle shall be whatever is given but if its not the full circle we dont need all the points!
     points = (int)(Mathf.Abs(endDegree - startDegree) / 360f * points);

     //We always need an uneven number of points!
     if (points % 2 != 0) { points++; }

     Vector3[] vertices = new Vector3[points];
     float degreeStepSize = (endDegree - startDegree) * 2 / (points - 3);
     float halfRadStepSize = (degreeStepSize) * Mathf.Deg2Rad / 2f;
     float startRad = Mathf.Deg2Rad * startDegree;
     float endRad = Mathf.Deg2Rad * endDegree;

     //Let's save the vector at the beginning and the one on the end to make a perfectly straight line
     vertices[0] = new Vector3(Mathf.Sin(startRad) * outerRadius + xPosition, Mathf.Cos(startRad) * outerRadius + yPosition, 0);
     vertices[vertices.Length - 1] = new Vector3(Mathf.Sin(endRad) * innerRadius + xPosition, Mathf.Cos(endRad) * innerRadius + yPosition, 0);

     for (int i = 1; i < vertices.Length - 1; i++)
     {
         //Pure coinsidence that saved some calculatons. Half Step Size is the same as what would needed to be calculated here!
         float rad = (i - 1) * halfRadStepSize + startRad;
         if (i % 2 == 0)
         {
             vertices[i].x = Mathf.Sin(rad) * outerRadius + xPosition;
             vertices[i].y = Mathf.Cos(rad) * outerRadius + yPosition;
             vertices[i].z = 0;
         }
         else
         {
             vertices[i].x = Mathf.Sin(rad) * innerRadius + xPosition;
             vertices[i].y = Mathf.Cos(rad) * innerRadius + yPosition;
             vertices[i].z = 0;;
         }
     }
     mesh.vertices = vertices;

     int[] tri = new int[(vertices.Length - 2) * 3];
     for (int i = 0; i < (vertices.Length - 2); i++)
     {
         int index = i * 3;
         if (i % 2 == 0)
         {
             tri[index + 0] = i + 0;
             tri[index + 1] = i + 2;
             tri[index + 2] = i + 1;
         }
         else
         {
             tri[index + 0] = i + 0;
             tri[index + 1] = i + 1;
             tri[index + 2] = i + 2;
         }
     }

     mesh.triangles = tri;
     Vector3[] normals = new Vector3[vertices.Length];
     Color[] colors = new Color[vertices.Length];

    var f = Vector3.forward;

     for (int i = 0; i < vertices.Length; i++)
     {
         normals[i].x= f.x;
         normals[i].y= f.y;
         normals[i].z= f.z;
         colors[i] = color;
     }
     mesh.normals = normals;
     mesh.colors = colors;

     meshFilter.mesh = mesh;
 }
Другие вопросы по тегам