9

I'm following this tutorial set: https://www.youtube.com/watch?v=owBt9SNKXCI&index=6&list=PLbghT7MmckI4qGA0Wm_TZS8LVrqS47I9R to dynamically build a tile map layout. It works to a point, but it generates a very strange layout with 128 x 128 sized tiles.

enter image description here

Clearly that strange partitioning shouldn't be happening, but I cannot seem to track down what's going on to cause it. Here is my version of the code, which is mostly identical to quill18creates's version sans a few small differences:

using UnityEngine;
using System.Collections;

[ExecuteInEditMode]
public class TileMap : MonoBehaviour {

    public int size_x = 100;
    public int size_z = 50;
    public float tileSize = 1.0f;

    public Texture2D terrainTiles;
    int tileResolution = 128;

    // Use this for initialization
    void Start () {
        BuildMesh();
    }

    Color[][] ChopUpTiles() {
        int numTilesPerRow = terrainTiles.width / tileResolution;
        int numRows = terrainTiles.height / tileResolution;

        Color[][] tiles = new Color[numTilesPerRow*numRows][];

        for(int y=0; y < numRows; y++) {
            for(int x=0; x < numTilesPerRow; x++) {
                tiles[y * numTilesPerRow + x] = terrainTiles.GetPixels( x*tileResolution , y*tileResolution, tileResolution, tileResolution );
            }
        }

        return tiles;
    }

    void BuildTexture() {
        //DTileMap map = new DTileMap(size_x, size_z);

        int texWidth = size_x * tileResolution;
        int texHeight = size_z * tileResolution;
        Texture2D texture = new Texture2D(texWidth, texHeight);

        Color[][] tiles = ChopUpTiles();


        for(int y=0; y < size_z; y++) {
            for(int x=0; x < size_x; x++) {
                Color[] p = tiles[Mathf.RoundToInt(Random.Range(0, 5))];
                texture.SetPixels(x * tileResolution, y * tileResolution, tileResolution, tileResolution, p);
            }
        }

        //texture.filterMode = FilterMode.Bilinear;
        texture.wrapMode = TextureWrapMode.Clamp;
        texture.Apply();

        MeshRenderer mesh_renderer = GetComponent<MeshRenderer>();
        mesh_renderer.sharedMaterials[0].mainTexture = texture;
    }

    public void BuildMesh() {
        int numTiles = size_x * size_z;
        int numTris = numTiles * 2;

        int vsize_x = size_x + 1;
        int vsize_z = size_z + 1;
        int numVerts = vsize_x * vsize_z;

        // Generate the mesh data
        Vector3[] vertices = new Vector3[ numVerts ];
        Vector3[] normals = new Vector3[numVerts];
        Vector2[] uv = new Vector2[numVerts];

        int[] triangles = new int[ numTris * 3 ];

        int x, z;
        for(z=0; z < vsize_z; z++) {
            for(x=0; x < vsize_x; x++) {
                vertices[ z * vsize_x + x ] = new Vector3( x*tileSize, 0, -z*tileSize );
                normals[ z * vsize_x + x ] = Vector3.up;
                uv[ (z * vsize_x) + x ] = new Vector2( (float)x / size_x, (float)z / size_z );
            }
        }
        Debug.Log ("Done Verts!");

        for(z=0; z < size_z; z++) {
            for(x=0; x < size_x; x++) {
                int squareIndex = z * size_x + x;
                int triOffset = squareIndex * 6;
                triangles[triOffset + 0] = z * vsize_x + x +           0;
                triangles[triOffset + 2] = z * vsize_x + x + vsize_x + 0;
                triangles[triOffset + 1] = z * vsize_x + x + vsize_x + 1;

                triangles[triOffset + 3] = z * vsize_x + x +           0;
                triangles[triOffset + 5] = z * vsize_x + x + vsize_x + 1;
                triangles[triOffset + 4] = z * vsize_x + x +           1;
            }
        }

        // Create a new Mesh and populate with the data
        Mesh mesh = new Mesh();
        mesh.vertices = vertices;
        mesh.triangles = triangles;
        mesh.normals = normals;
        mesh.uv = uv;

        // Assign our mesh to our filter/renderer/collider
        MeshFilter mesh_filter = GetComponent<MeshFilter>();
        MeshCollider mesh_collider = GetComponent<MeshCollider>();

        mesh_filter.mesh = mesh;
        mesh_collider.sharedMesh = mesh;


        BuildTexture();
    }   
}
Merlin
  • 929
  • 12
  • 33
  • Anyone willing to take a crack at this? I like this idea for the code, I just can't seem to get the UV positioning layout working the way it should work. – Merlin Aug 17 '15 at 01:17
  • Could you post what the differences are? It seems like that's where you'd want to look. – 31eee384 Aug 19 '15 at 22:02

2 Answers2

2

I don't get exactly what part is wrong in the image but I think it is that the same tiles are lumping together. I tried your code and it works well for me. But I guess the following part could be causing the lumping together problem for you:

Color[] p = tiles[Mathf.RoundToInt(Random.Range(0, 5))];

Instead you should do:

Color[] p = tiles[Random.Range(0, 5)];

Because, the other way, Random is generating float numbers and maybe they are near the each other that rounding them to the integer gives same tile. Give it a try. Also just reminding, make sure the width and the height of your texture is divisible by 128.

Gokhan Kurt
  • 8,239
  • 1
  • 27
  • 51
  • Mostly off I'm afraid, although I believe it might be the ChopUpTiles function causing this. I'm just not sure how. – Merlin Aug 19 '15 at 03:10
  • I think I reproduced the problem. The maximum texture size you can have in Unity is 2^14 by 2^14. When you try to produce a larger texture it gives an exception when creating the texture but mesh is created anyways. So the texture stretches along the mesh and it looks like tiles are lumping together. One dimension of your texture size is decided by `size_x * tileResolution`. So when you try to create a larger mesh, you will get this error. – Gokhan Kurt Aug 19 '15 at 16:32
  • Anyways I noticed this is a bad way to create this kind of mesh. You may create more than one mesh to have a bigger world but I still think it is not a good way. Instead you should do it like this: Use 4 vertices for every tile. Assign uv coordinates according to their position on the original texture. And use the original texture in the material. So don't create a new texture. This way you can have any size mesh as long as it has less than 64k vertices. Then again there is no way to overcome 64k vertices so you have to create another mesh if you want to make it bigger. – Gokhan Kurt Aug 19 '15 at 16:36
  • However I am still not sure if you get this error. I think you would state it explicitly if you got the exception. – Gokhan Kurt Aug 19 '15 at 16:41
  • The funny thing is that the tilemap the original gives is much larger, although the actual tiles are smaller. However, this might be the issue. I'll have to experiment with this suggestion. – Merlin Aug 21 '15 at 05:14
0

Well, it was definitely a size issue, but there was also an issue with positioning. Tiles have to start at the bottom-left corner for the coordinate system to find them.

Merlin
  • 929
  • 12
  • 33