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};