Home > Back-end >  The length of this integer array is 0?
The length of this integer array is 0?

Time:11-16

I've been trying to create a plane mesh in Unity using code, and I've come across a very interesting problem. I created an int[], filled it up with some values, and it's length is somehow zero. I've never encountered anything this quirky, so I'd enjoy a bit of help.

mesh.triangles = new int[]
{
    4, 6, 5, 5, 6, 7
};
... // Not important stuff
Debug.Log(mesh.triangles.Length);

I don't know what is happening, so I really haven't tried anything. But in the console, there is an error message stating Failed setting triangles. Some indices are referencing out of bounds vertices. IndexCount: 6, VertexCount: 4.This is probably really important, but I don't understand some parts of the message(especially the last part). And if it makes a difference, I have an array concatenation method being called to add the first triangles to these ones. I initially identified this problem when the half of my mesh still wasn't appearing. I would really appreciate help; thanks.

Edit: To cut confusion, I'm just going to paste my whole entire method.

private void CreateQuad(ref Mesh mesh, Vector3 offset, bool first)
    {
        if (first)
        {
            mesh.vertices = new Vector3[]
            {
                Vector3.zero, Vector3.right, Vector3.forward, new Vector3(1, 0, 1)
            };
            mesh.triangles = new int[]
            {
                0, 2, 1, 1, 2, 3
            };
            mesh.normals = new Vector3[]
            {
                Vector3.back, Vector3.back, Vector3.back, Vector3.back
            };
            mesh.tangents = new Vector4[]
            {
                new Vector4(1, 0, 0, -1),
                new Vector4(1, 0, 0, -1),
                new Vector4(1, 0, 0, -1),
                new Vector4(1, 0, 0, -1)
            };
            mesh.uv = new Vector2[]
            {
                Vector2.zero, Vector2.right, Vector2.up, Vector2.one
            };
        }
        else if (!first)
        {
            mesh.vertices = new Vector3[]
            {
                Vector3.zero   offset,
                Vector3.right   offset,
                Vector3.forward   offset,
                new Vector3(1, 0, 1)   offset
            };
            mesh.triangles = new int[]
            {
                4, 6, 5, 5, 6, 7
            };
            mesh.normals = new Vector3[]
            {
                Vector3.back, Vector3.back, Vector3.back, Vector3.back
            };
            mesh.tangents = new Vector4[]
            {
                new Vector4(1, 0, 0, -1),
                new Vector4(1, 0, 0, -1),
                new Vector4(1, 0, 0, -1),
                new Vector4(1, 0, 0, -1)
            };
            mesh.uv = new Vector2[]
            {
                Vector2.zero, Vector2.right, Vector2.up, Vector2.one
            };
            Debug.Log(mesh.triangles.Length);
        }
    }

CodePudding user response:

You only have FOUR vertices!

mesh.vertices = new Vector3[]
{
    Vector3.zero   offset,
    Vector3.right   offset,
    Vector3.forward   offset,
    new Vector3(1, 0, 1)   offset
};

So the indices 4, 6, 5, 5, 6, 7 are all invalid! If you have only four vertices you can maximum have the indices 0, 1, 2, 3

=> Unity simply rejects them all. You should have already taken that hint from the error you get

Failed setting triangles. Some indices are referencing out of bounds vertices. IndexCount: 6, VertexCount: 4


Now it is a bit unclear what exactly you are trying to achieve here but

  • either you want to REPLACE the vertices: In this case there is no reason to set new triangle instances etc at all! It is enough to connect them only once:

      private void CreateQuad(ref Mesh mesh, Vector3 offset, bool first)
      {
          if (first)
          {
              mesh.vertices = new Vector3[]
              {
                  Vector3.zero, Vector3.right, Vector3.forward, new Vector3(1, 0, 1)
              };
              mesh.triangles = new int[]
              {
                  0, 2, 1, 1, 2, 3
              };
              mesh.normals = new Vector3[]
              {
                  Vector3.back, Vector3.back, Vector3.back, Vector3.back
              };
              mesh.tangents = new Vector4[]
              {
                  new Vector4(1, 0, 0, -1),
                  new Vector4(1, 0, 0, -1),
                  new Vector4(1, 0, 0, -1),
                  new Vector4(1, 0, 0, -1)
              };
              mesh.uv = new Vector2[]
              {
                  Vector2.zero, Vector2.right, Vector2.up, Vector2.one
              };
          }
          else if (!first)
          {
              mesh.vertices = new Vector3[]
              {
                  Vector3.zero   offset,
                  Vector3.right   offset,
                  Vector3.forward   offset,
                  new Vector3(1, 0, 1)   offset
              };
          }
      }
    

    the other properties can simply be left untouched since you only want to update the vertex positions.

  • Or you actually wanted to ADD more faces. In that case you rather want to append to the existing arrays:

     private void CreateQuad(ref Mesh mesh, Vector3 offset, bool first)
     {
         if (first)
         {
             mesh.vertices = new Vector3[]
             {
                 Vector3.zero, Vector3.right, Vector3.forward, new Vector3(1, 0, 1)
             };
             mesh.triangles = new int[]
             {
                 0, 2, 1, 1, 2, 3
             };
             mesh.normals = new Vector3[]
             {
                 Vector3.back, Vector3.back, Vector3.back, Vector3.back
             };
             mesh.tangents = new Vector4[]
             {
                 new Vector4(1, 0, 0, -1),
                 new Vector4(1, 0, 0, -1),
                 new Vector4(1, 0, 0, -1),
                 new Vector4(1, 0, 0, -1)
             };
             mesh.uv = new Vector2[]
             {
                 Vector2.zero, Vector2.right, Vector2.up, Vector2.one
             };
         }
         else if (!first)
         {
             // fist get already existing verts etc
             var oldVerts = mesh.vertices;
             var oldTris = mesh.triangles;
    
             // create new vertices and triangles arrays with additional space for the new quad
             var newVerts = new Vector3[oldVerts.Length   4];
             var newTris = new int[oldTris.Length   6];
    
             // copy over the existing vertices and triangles
             Array.Copy(oldVerts, newVerts, olVerts.Length);
             Array.Copy(oldTris, newtris, oldtris.Length);
    
             // then append the new vertices
             newVerts[oldverts.Length   0] = Vector3.zero   offset;
             newVerts[oldverts.Length   1] = Vector3.right   offset;
             newVerts[oldverts.Length   2] = Vector3.forward   offset;
             newVerts[oldverts.Length   3] = new Vector3(1, 0, 1)   offset;
    
             // append the new triangles
             newTris[oldTris.Length   0] = oldverts.Length   0;
             newTris[oldTris.Length   1] = oldverts.Length   2;
             newTris[oldTris.Length   2] = oldverts.Length   1;
             newTris[oldTris.Length   3] = oldverts.Length   1;
             newTris[oldTris.Length   4] = oldverts.Length   2;
             newTris[oldTris.Length   5] = oldverts.Length   3;
    
             // get the min and max points for filling the uvs (not the most efficient way probably but it is what it is ^^)
             // we later want to spread out the UV values linear between 0 (min) and 1 (max) on the given vertices
             var min = Vector3.zero;
             var max = Vector3.zero;
             foreach(var vertex in newVerts)
             {
                min = Vector3.Min(min, vertex);
                max = Vector3.Max(max, vertex);
             }
    
             // also fill new tangents and normals and uvs (if really necessary)
             var newNormals = new Vector3[newVerts.Length];
             var newTangents = new Vector4[newVerts.Length];
             var newUVs = new Vector2[newVerts.Length];
             for(var i = 0; i < newVerts.Length; i  )
             {
                 var vertex = newVerts[i];
                 newUVs[i] = new Vector2((vertex.x - min.x) / (max.x - min.x), (vertex.z - min.z) / (max.z - min.z));
                 newNormals[i] = Vector3.back;
                 newTangents[i] = new Vector4(1, 0, 0, -1);
             };
    
             // finally set them all back
             mesh.vertices = newVerts;
             mesh.triangles = newTris;
             mesh.normals = newNormals;
             mesh.tangents = newTangents;
             mesh.uv = newUs;
         }
     }
    

CodePudding user response:

You first need to set the vertex array before altering the triangles. As Unity writes "It is recommended to assign a triangle array after assigning the vertex array, in order to avoid out of bounds errors."

mesh.vertices = new Vector3[] { new Vector3(-1,0,1), new Vector3(-1,0,-1),
    new Vector3(1,0,-1), new Vector3(1,0,1) };
mesh.triangles = new int[] {0,1,2,0,2,3};
  • Related