1

I'm creating a mesh programmatically in Unity3D. Each section of the mesh is setup with 4 verts:

// 1 ----- 2 
// | a  /  |
// |  /  b |
// 3 ----- 4

My UVs are:

1 = 0, 1
2 = 0.125, 1
3 = 0, 0.875
4 = 0.125, 0.875

My texture is 2048x2048. The tile is in the top left of the image and is 256x256 in size. I've updated the texture a bit with some additional tiles to better give an idea of what I'm trying to do.

Tilemap

Im getting white edges around each tile on the mesh.

Screenshot

I'm importing the image with the following settings.

Import settings

The code the generate the mesh (manual normals):

IEnumerator BuildMesh (int width, int height, float tileSize) {

    float halfSize = tileSize / 2f;

    List<Vector3> vertices = new List<Vector3> ();
    List<Vector3> normals = new List<Vector3> ();
    List<Vector2> uv = new List<Vector2> ();
    List<int> triangles = new List<int> ();

    for (int y = 0; y < height; y++) {
        for (int x = 0; x < width; x++) {
            int tileVertIdx = vertices.Count;

            float h = map.GetHeight(startX + x, startY + y);
            float n = map.GetHeight(startX + x, startY + y - 1);
            float s = map.GetHeight(startX + x, startY + y + 1);
            float e = map.GetHeight(startX + x + 1, startY + y);
            float w = map.GetHeight(startX + x - 1, startY + y);
            float ne = map.GetHeight(startX + x + 1, startY + y - 1);
            float nw = map.GetHeight(startX + x - 1, startY + y - 1);
            float se = map.GetHeight(startX + x + 1, startY + y + 1);
            float sw = map.GetHeight(startX + x - 1, startY + y + 1);

            Vector3 tileCenter = new Vector3 (x * tileSize, h, y * tileSize);
            Rect topUV = map.GetTopUV ((int)h);

            if (n == h && s == h && e == h && w == h && ne == h && nw == h && se == h && sw == h) {
                // Each tile
                // 1 ----- 2 
                // | a  /  |
                // |  /  b |
                // 3 ----- 4

                // top row
                vertices.Add (new Vector3 (tileCenter.x - halfSize, tileCenter.y, tileCenter.z - halfSize));
                vertices.Add (new Vector3 (tileCenter.x + halfSize, tileCenter.y, tileCenter.z - halfSize));

                // bottom row
                vertices.Add (new Vector3 (tileCenter.x - halfSize, tileCenter.y, tileCenter.z + halfSize));
                vertices.Add (new Vector3 (tileCenter.x + halfSize, tileCenter.y, tileCenter.z + halfSize));

                normals.Add (Vector3.up);
                normals.Add (Vector3.up);

                normals.Add (Vector3.up);
                normals.Add (Vector3.up);

                uv.Add (new Vector2(topUV.x, topUV.y));
                uv.Add (new Vector2(topUV.x - topUV.width, topUV.y));

                uv.Add (new Vector2(topUV.x, topUV.y - topUV.height));
                uv.Add (new Vector2(topUV.x - topUV.width, topUV.y - topUV.height));

                // a
                triangles.Add (tileVertIdx + 0);
                triangles.Add (tileVertIdx + 2);
                triangles.Add (tileVertIdx + 1);

                // b
                triangles.Add (tileVertIdx + 1);
                triangles.Add (tileVertIdx + 2);
                triangles.Add (tileVertIdx + 3);
            } else {
                // Each tile
                // 1 - 2 - 3 14 --- 16
                // |a\b|c/d\ |  k / |
                // 4 - 5 - 6 |   /  |
                // |e/f|g\h| |  / l |
                // 7 - 8 - 9 15 --- 17
                // 10 --- 11
                // | i / j |
                // 12 --- 13

                // top row
                vertices.Add (new Vector3 (tileCenter.x - halfSize, tileCenter.y, tileCenter.z - halfSize));
                vertices.Add (new Vector3 (tileCenter.x, tileCenter.y, tileCenter.z - halfSize));
                vertices.Add (new Vector3 (tileCenter.x + halfSize, tileCenter.y, tileCenter.z - halfSize));

                // middle row
                vertices.Add (new Vector3 (tileCenter.x - halfSize, tileCenter.y, tileCenter.z));
                vertices.Add (new Vector3 (tileCenter.x, tileCenter.y, tileCenter.z));
                vertices.Add (new Vector3 (tileCenter.x + halfSize, tileCenter.y, tileCenter.z));

                // bottom row
                vertices.Add (new Vector3 (tileCenter.x - halfSize, tileCenter.y, tileCenter.z + halfSize));
                vertices.Add (new Vector3 (tileCenter.x, tileCenter.y, tileCenter.z + halfSize));
                vertices.Add (new Vector3 (tileCenter.x + halfSize, tileCenter.y, tileCenter.z + halfSize));

                // bottom square
                vertices.Add (new Vector3 (tileCenter.x - halfSize, h, tileCenter.z + halfSize));
                vertices.Add (new Vector3 (tileCenter.x + halfSize, h, tileCenter.z + halfSize));
                vertices.Add (new Vector3 (tileCenter.x - halfSize, s, tileCenter.z + halfSize));
                vertices.Add (new Vector3 (tileCenter.x + halfSize, s, tileCenter.z + halfSize));

                // right square
                vertices.Add (new Vector3 (tileCenter.x + halfSize, h, tileCenter.z + halfSize));
                vertices.Add (new Vector3 (tileCenter.x + halfSize, h, tileCenter.z - halfSize));
                vertices.Add (new Vector3 (tileCenter.x + halfSize, e, tileCenter.z + halfSize));
                vertices.Add (new Vector3 (tileCenter.x + halfSize, e, tileCenter.z - halfSize));

                normals.Add (Vector3.up);
                normals.Add (Vector3.up);
                normals.Add (Vector3.up);

                normals.Add (Vector3.up);
                normals.Add (Vector3.up);
                normals.Add (Vector3.up);

                normals.Add (Vector3.up);
                normals.Add (Vector3.up);
                normals.Add (Vector3.up);

                normals.Add (Vector3.up);
                normals.Add (Vector3.up);
                normals.Add (Vector3.up);
                normals.Add (Vector3.up);

                normals.Add (Vector3.up);
                normals.Add (Vector3.up);
                normals.Add (Vector3.up);
                normals.Add (Vector3.up);

                uv.Add (new Vector2(topUV.x, topUV.y));
                uv.Add (new Vector2(topUV.x - (topUV.width / 2), topUV.y));
                uv.Add (new Vector2(topUV.x - topUV.width, topUV.y));

                uv.Add (new Vector2(topUV.x, topUV.y - (topUV.height / 2)));
                uv.Add (new Vector2(topUV.x - (topUV.width / 2), topUV.y - (topUV.height / 2)));
                uv.Add (new Vector2(topUV.x - topUV.width, topUV.y - (topUV.height / 2)));

                uv.Add (new Vector2(topUV.x, topUV.y - topUV.height));
                uv.Add (new Vector2(topUV.x - (topUV.width / 2), topUV.y - topUV.height));
                uv.Add (new Vector2(topUV.x - topUV.width, topUV.y - topUV.height));

                uv.Add (Vector2.up);
                uv.Add (Vector2.up);
                uv.Add (Vector2.up);
                uv.Add (Vector2.up);

                uv.Add (Vector2.up);
                uv.Add (Vector2.up);
                uv.Add (Vector2.up);
                uv.Add (Vector2.up);

                // a
                triangles.Add (tileVertIdx + 0);
                triangles.Add (tileVertIdx + 3);
                triangles.Add (tileVertIdx + 4);

                // b
                triangles.Add (tileVertIdx + 0);
                triangles.Add (tileVertIdx + 4);
                triangles.Add (tileVertIdx + 1);

                // c
                triangles.Add (tileVertIdx + 1);
                triangles.Add (tileVertIdx + 4);
                triangles.Add (tileVertIdx + 2);

                // d
                triangles.Add (tileVertIdx + 2);
                triangles.Add (tileVertIdx + 4);
                triangles.Add (tileVertIdx + 5);

                // e
                triangles.Add (tileVertIdx + 3);
                triangles.Add (tileVertIdx + 6);
                triangles.Add (tileVertIdx + 4);

                // f
                triangles.Add (tileVertIdx + 4);
                triangles.Add (tileVertIdx + 6);
                triangles.Add (tileVertIdx + 7);

                // g
                triangles.Add (tileVertIdx + 4);
                triangles.Add (tileVertIdx + 7);
                triangles.Add (tileVertIdx + 8);

                // h
                triangles.Add (tileVertIdx + 4);
                triangles.Add (tileVertIdx + 8);
                triangles.Add (tileVertIdx + 5);

                // i
                triangles.Add (tileVertIdx + 9);
                triangles.Add (tileVertIdx + 11);
                triangles.Add (tileVertIdx + 10);

                // j
                triangles.Add (tileVertIdx + 10);
                triangles.Add (tileVertIdx + 11);
                triangles.Add (tileVertIdx + 12);

                // k
                triangles.Add (tileVertIdx + 13);
                triangles.Add (tileVertIdx + 15);
                triangles.Add (tileVertIdx + 14);

                // l
                triangles.Add (tileVertIdx + 15);
                triangles.Add (tileVertIdx + 16);
                triangles.Add (tileVertIdx + 14);
            }
        }
        yield return null;
    }

    Mesh mesh = _meshFilter.mesh;
    mesh.vertices = vertices.ToArray ();
    mesh.triangles = triangles.ToArray ();
    mesh.normals = normals.ToArray ();
    mesh.uv = uv.ToArray ();
//  mesh.RecalculateNormals ();
//  mesh.Optimize ();
    map.ChunkFinished ();
}

The code to generate the mesh (auto normals):

IEnumerator BuildMesh (int width, int height, float tileSize) {

    float halfSize = tileSize / 2f;

    List<Vector3> vertices = new List<Vector3> ();
    List<Vector3> normals = new List<Vector3> ();
    List<Vector2> uv = new List<Vector2> ();
    List<int> triangles = new List<int> ();

    for (int y = 0; y < height; y++) {
        for (int x = 0; x < width; x++) {
            int tileVertIdx = vertices.Count;

            float h = map.GetHeight(startX + x, startY + y);
            float n = map.GetHeight(startX + x, startY + y - 1);
            float s = map.GetHeight(startX + x, startY + y + 1);
            float e = map.GetHeight(startX + x + 1, startY + y);
            float w = map.GetHeight(startX + x - 1, startY + y);
            float ne = map.GetHeight(startX + x + 1, startY + y - 1);
            float nw = map.GetHeight(startX + x - 1, startY + y - 1);
            float se = map.GetHeight(startX + x + 1, startY + y + 1);
            float sw = map.GetHeight(startX + x - 1, startY + y + 1);

            Vector3 tileCenter = new Vector3 (x * tileSize, h, y * tileSize);
            Rect topUV = map.GetTopUV ((int)h);

            if (n == h && s == h && e == h && w == h && ne == h && nw == h && se == h && sw == h) {
                // Each tile
                // 1 ----- 2 
                // | a  /  |
                // |  /  b |
                // 3 ----- 4

                // top row
                vertices.Add (new Vector3 (tileCenter.x - halfSize, tileCenter.y, tileCenter.z - halfSize));
                vertices.Add (new Vector3 (tileCenter.x + halfSize, tileCenter.y, tileCenter.z - halfSize));

                // bottom row
                vertices.Add (new Vector3 (tileCenter.x - halfSize, tileCenter.y, tileCenter.z + halfSize));
                vertices.Add (new Vector3 (tileCenter.x + halfSize, tileCenter.y, tileCenter.z + halfSize));

                uv.Add (new Vector2(topUV.x, topUV.y));
                uv.Add (new Vector2(topUV.x - topUV.width, topUV.y));

                uv.Add (new Vector2(topUV.x, topUV.y - topUV.height));
                uv.Add (new Vector2(topUV.x - topUV.width, topUV.y - topUV.height));

                // a
                triangles.Add (tileVertIdx + 0);
                triangles.Add (tileVertIdx + 2);
                triangles.Add (tileVertIdx + 1);

                // b
                triangles.Add (tileVertIdx + 1);
                triangles.Add (tileVertIdx + 2);
                triangles.Add (tileVertIdx + 3);
            } else {
                // Each tile
                // 1 - 2 - 3 14 --- 16
                // |a\b|c/d\ |  k / |
                // 4 - 5 - 6 |   /  |
                // |e/f|g\h| |  / l |
                // 7 - 8 - 9 15 --- 17
                // 10 --- 11
                // | i / j |
                // 12 --- 13

                // top row
                vertices.Add (new Vector3 (tileCenter.x - halfSize, tileCenter.y, tileCenter.z - halfSize));
                vertices.Add (new Vector3 (tileCenter.x, tileCenter.y, tileCenter.z - halfSize));
                vertices.Add (new Vector3 (tileCenter.x + halfSize, tileCenter.y, tileCenter.z - halfSize));

                // middle row
                vertices.Add (new Vector3 (tileCenter.x - halfSize, tileCenter.y, tileCenter.z));
                vertices.Add (new Vector3 (tileCenter.x, tileCenter.y, tileCenter.z));
                vertices.Add (new Vector3 (tileCenter.x + halfSize, tileCenter.y, tileCenter.z));

                // bottom row
                vertices.Add (new Vector3 (tileCenter.x - halfSize, tileCenter.y, tileCenter.z + halfSize));
                vertices.Add (new Vector3 (tileCenter.x, tileCenter.y, tileCenter.z + halfSize));
                vertices.Add (new Vector3 (tileCenter.x + halfSize, tileCenter.y, tileCenter.z + halfSize));

                // bottom square
                vertices.Add (new Vector3 (tileCenter.x - halfSize, h, tileCenter.z + halfSize));
                vertices.Add (new Vector3 (tileCenter.x + halfSize, h, tileCenter.z + halfSize));
                vertices.Add (new Vector3 (tileCenter.x - halfSize, s, tileCenter.z + halfSize));
                vertices.Add (new Vector3 (tileCenter.x + halfSize, s, tileCenter.z + halfSize));

                // right square
                vertices.Add (new Vector3 (tileCenter.x + halfSize, h, tileCenter.z + halfSize));
                vertices.Add (new Vector3 (tileCenter.x + halfSize, h, tileCenter.z - halfSize));
                vertices.Add (new Vector3 (tileCenter.x + halfSize, e, tileCenter.z + halfSize));
                vertices.Add (new Vector3 (tileCenter.x + halfSize, e, tileCenter.z - halfSize));

                uv.Add (new Vector2(topUV.x, topUV.y));
                uv.Add (new Vector2(topUV.x - (topUV.width / 2), topUV.y));
                uv.Add (new Vector2(topUV.x - topUV.width, topUV.y));

                uv.Add (new Vector2(topUV.x, topUV.y - (topUV.height / 2)));
                uv.Add (new Vector2(topUV.x - (topUV.width / 2), topUV.y - (topUV.height / 2)));
                uv.Add (new Vector2(topUV.x - topUV.width, topUV.y - (topUV.height / 2)));

                uv.Add (new Vector2(topUV.x, topUV.y - topUV.height));
                uv.Add (new Vector2(topUV.x - (topUV.width / 2), topUV.y - topUV.height));
                uv.Add (new Vector2(topUV.x - topUV.width, topUV.y - topUV.height));

                uv.Add (Vector2.up);
                uv.Add (Vector2.up);
                uv.Add (Vector2.up);
                uv.Add (Vector2.up);

                uv.Add (Vector2.up);
                uv.Add (Vector2.up);
                uv.Add (Vector2.up);
                uv.Add (Vector2.up);

                // a
                triangles.Add (tileVertIdx + 0);
                triangles.Add (tileVertIdx + 3);
                triangles.Add (tileVertIdx + 4);

                // b
                triangles.Add (tileVertIdx + 0);
                triangles.Add (tileVertIdx + 4);
                triangles.Add (tileVertIdx + 1);

                // c
                triangles.Add (tileVertIdx + 1);
                triangles.Add (tileVertIdx + 4);
                triangles.Add (tileVertIdx + 2);

                // d
                triangles.Add (tileVertIdx + 2);
                triangles.Add (tileVertIdx + 4);
                triangles.Add (tileVertIdx + 5);

                // e
                triangles.Add (tileVertIdx + 3);
                triangles.Add (tileVertIdx + 6);
                triangles.Add (tileVertIdx + 4);

                // f
                triangles.Add (tileVertIdx + 4);
                triangles.Add (tileVertIdx + 6);
                triangles.Add (tileVertIdx + 7);

                // g
                triangles.Add (tileVertIdx + 4);
                triangles.Add (tileVertIdx + 7);
                triangles.Add (tileVertIdx + 8);

                // h
                triangles.Add (tileVertIdx + 4);
                triangles.Add (tileVertIdx + 8);
                triangles.Add (tileVertIdx + 5);

                // i
                triangles.Add (tileVertIdx + 9);
                triangles.Add (tileVertIdx + 11);
                triangles.Add (tileVertIdx + 10);

                // j
                triangles.Add (tileVertIdx + 10);
                triangles.Add (tileVertIdx + 11);
                triangles.Add (tileVertIdx + 12);

                // k
                triangles.Add (tileVertIdx + 13);
                triangles.Add (tileVertIdx + 15);
                triangles.Add (tileVertIdx + 14);

                // l
                triangles.Add (tileVertIdx + 15);
                triangles.Add (tileVertIdx + 16);
                triangles.Add (tileVertIdx + 14);
            }
        }
        yield return null;
    }

    Mesh mesh = _meshFilter.mesh;
    mesh.vertices = vertices.ToArray ();
    mesh.triangles = triangles.ToArray ();
    mesh.uv = uv.ToArray ();
    mesh.RecalculateNormals ();
    mesh.Optimize ();

    map.ChunkFinished ();
}

Both versions of the code produce the same issue.

JeanLuc
  • 4,783
  • 1
  • 33
  • 47
Justin808
  • 20,859
  • 46
  • 160
  • 265
  • what's up with the .125 business? wouldn't it just be 1,1 etc .. all 1/0?? – Fattie Feb 28 '16 at 23:43
  • @JoeBlow - Its not the full image size. I only have 1 tile on there at the moment but there will be a lot more, grass, dirt, water, etc. I'm just trying to get the texture to line up properly at the moment. – Justin808 Feb 29 '16 at 00:08
  • ok - just a suggestion: just make a normal quad in unity (ie use menu). put your texture on it. fool with the values until they are as you wish. Absolutely check it looks correct ON THE UNITY SUPPLIED MESH! – Fattie Feb 29 '16 at 00:23
  • I'm trying to make a tiled map, on a single mesh. The mesh is not just a plane so I can't use the supplied mesh. If it helps I'll post my code. – Justin808 Feb 29 '16 at 00:50
  • did you google these lame ideas ? http://forum.unity3d.com/threads/black-lines-on-the-edges-of-tiled-sprites.226919/ – Fattie Feb 29 '16 at 01:07
  • @JoeBlow - I tried on a quad and I see the same white line. – Justin808 Feb 29 '16 at 01:12
  • hey @justin808 ! did you ever solve this one, I'd be interested to know – Fattie Jul 16 '16 at 16:04

3 Answers3

1

Dude are your normals ok?

They should all be pointing straight up for this jobbie right?

If you're using some default normal calculation, could it be they're trying to gently wrap the edge thinking it's a cube?

Fattie
  • 27,874
  • 70
  • 431
  • 719
  • I've tried both ways, everything pointing up and using the build in `RecalculateNormals` – Justin808 Feb 29 '16 at 00:48
  • oh don't use Recalc. normals. you're ***1000%*** certain your normals were correct?? – Fattie Feb 29 '16 at 00:51
  • are you *totally sure* it is not working over you and doing `RecalculateStupidNormals` on its own? there's some point where it does that for you "helpfully" automatically. drives people nuts – Fattie Feb 29 '16 at 00:52
  • I'm 99% certain it's your normals. To test: just zoom in really close and see if Unity is trying to make it a nice smooth edge. Print out with debug or something the actual final normals (don't trust that you set them as you wish) – Fattie Feb 29 '16 at 00:54
0

Try setting the format to Truecolor. It might be that due to the compression the borders between the different textures are not sharp anymore but blurred, causing them to bleed into each other.

Thomas Hilbert
  • 3,559
  • 2
  • 13
  • 33
0

i have the similar problem no filter (point) is not realy no filter there is a nearest neighbour unity builtin filter behind no filter

for resolve your issue you must split your texture into 4 splited textures by this way create 4 new texture2D() store all pixels of orginal texture into an 2D array by get pixel method https://docs.unity3d.com/ScriptReference/Texture2D.GetPixel.html and create 4 new texture and use use 4 for loop to get quarter of orginal texture pixels and set the pixels to one of destination textures https://docs.unity3d.com/ScriptReference/Texture2D.SetPixel.html https://docs.unity3d.com/ScriptReference/Texture2D.SetPixel.html

ehsan wwe
  • 71
  • 2
  • 9