What is wrong with my UVs?

I have created a cube from 6 planes, when I set their texture the sides are all stretched… The green lines are my normals.

How have you set the UVs? You have made this cube from 36 vertices right?

each one of those green lines is on a vertice... I just need to figure out how to paint the texture onto the side, as its a separate object. As I am building/triangulating the plain proceduraly, Do I need to rotate my transform before assigning my vertice/triangles to it?

As long as your UVs are linearly interpolated between 0 and 1 as you move from side to side, you should be good. Have any code where you do that?

Here is where I build my UVs, is it something in here that is defining how they display? for (int side = 0; side < CubeSides.Count; side++) { for (int j = 0; j < filter1.mesh.vertices.Length; j++) { filter1 = CubeSides[side].gameObject.GetComponent<MeshFilter>(); sideNormals[side].Add(filter1.mesh.vertices[j]); uvs.Add (new Vector2( filter1.mesh.vertices[j].x filter1.mesh.vertices[j].z } filter1.mesh.uv = uvs.ToArray();}

I presume you are going to deform this mesh otherwise it's a lot of vertices and triangles you don't need...

2 Answers

2

The uv values should be in the range 0…1: in a face, the lower left corner has uv = 0,0 and the top right corner has uv = 1,1

If you’re using the standard Unity plane primitive, its vertex coordinates range from -5,0,-5 to 5,0,5 - you should thus divide the x or z coordinate of each vertex by 10 and add 0.5 to shift the result to the range 0…1:

             uvs.Add (new Vector2(
                  filter1.mesh.vertices[j].x/10+0.5f;
                  filter1.mesh.vertices[j].z/10+0.5f;
             }

But your code can be a lot faster if you use fixed arrays and avoid redundant operations inside the loop - like this:

for (int side = 0; side < CubeSides.Count; side++) {
    filter1 = CubeSides[side].gameObject.GetComponent<MeshFilter>();
    Mesh mesh = filter1.mesh;
    int nVerts = mesh.vertices.Length;
    Vector3[] normals = new Vector3[nVerts];
    Vector2[] uvs = new Vector2[nVerts];
    for (int j = 0; j < nVerts; j++){
        normals[j] = Vector3.up;
        Vector3 vertx = mesh.vertices[j];
        uvs[j] = new Vector2(vertx.x/10+0.5f, vertex.z/10+0.5f);
    }
    mesh.normals = normals;
    mesh.uv = uvs;
}

I will also be shortcutting my property calls after I get everything functioning ;)

I figured it out, I just needed to actually think about what I was trying to achieve.

Here is the working code:

                int sideVerts = filter1.mesh.vertices.Length;
    			for (int j = 0; j < sideVerts; j++) {
    				Vector3 vert = filter1.mesh.vertices[j];
    				sideNormals[side].Add(vert);
    				uvs.Add (new Vector2(
    					(1/(units+1))*(j%(units+1)),
    					(1/(units+1))*(Mathf.Floor(j/(units+1))))); 
    			}

Glad to hear you got it working. One thing to note in your code above, however: Every time you access mesh.vertices (or mesh.triangles, mesh.normals, mesh.uvs, etc.) you are getting a copy of the array, not a reference. So in your code above, you'll get a complete array copy of the vertices in every cycle through the for loop. For efficiency, best to get a copy initially, then use it in your for loop. Vector3[] vertices = filter1.mesh.vertices; for(int j=0; j<sideVerts; j++) { Vector3 vert = vertices[j]; ...

Excellent point, much appreciated :)