Creating a tilemap from using a script

I am trying to create a tile map by using a script. I know there are different other methods to do it but its for learning purposes. It would really be cool if it works, so I can put it in my guitar hero game or rpg.

The script created my tilemap too big. It spawned extra tiles, which made my tile map too big. If I put one different tile on the tile map, it made like 6 extra of that tile. My tile map layer is 128x128 px and the script made it like 10x times as big. My default tiles are 32x32px.

This script basically reads the color per unit of your map layer png file. It spawns a tile based on the color to whatever you input it.

I recommend you to save your project before trying this out though. It might break unity if you mistype something.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;

public class LevelManager : MonoBehaviour
{
    [SerializeField]
    private Transform map;

    [SerializeField]
    private Texture2D[] mapData;

    [SerializeField]
    private MapElement[] mapElements;

    [SerializeField]
    private Sprite defaultTile;


    private Vector3 WorldStartPos
    {
        get
        {
            return Camera.main.ScreenToWorldPoint(new Vector3(0, 0));
        }
    }

    // Start is called before the first frame update
    void Start()
    {
        GenerateMap();
    }

    private void GenerateMap()
    {
        int height = mapData[0].height;
        int width = mapData[0].width;

        for (int i = 0; i < mapData.Length; i++)
        {
            for (int x = 0; x < mapData[i].width; x++)
            {
                for (int y = 0; y < mapData[i].height; y++)
                {
                    Color c = mapData[i].GetPixel(x, y); //Gets the color of the current pixel

                    MapElement newElement = Array.Find(mapElements, e => e.MyColor == c);

                    if (newElement != null)
                    {
                        float xPos = WorldStartPos.x + (defaultTile.bounds.size.x * x);
                        float yPos = WorldStartPos.y + (defaultTile.bounds.size.y * y);

                        GameObject go = Instantiate(newElement.MyElementPrefab);
                        go.transform.position = new Vector2(xPos, yPos);

                        if (newElement.MyTileTag == "Tree")
                        {
                            go.GetComponent<SpriteRenderer>().sortingOrder = height*2 - y*2;
                        }
                        go.transform.parent = map;
                    }
                }
            }
        }
    }
}

[Serializable]
public class MapElement
{
    [SerializeField]
    private string tileTag;

    [SerializeField]
    private Color color;

    [SerializeField]
    private GameObject elementPrefab;

    public GameObject MyElementPrefab
    {
        get
        {
            return elementPrefab;
        }
    }

    public Color MyColor
    {
        get
        {
            return color;
        }
    }

    public string MyTileTag
    {
        get
        {
            return tileTag;
        }
    }
}

Since we don’t know what’s in your mapData texture array, this is going to be difficult for us to debug. But from afar, I’m a bit surprised that you are trying to set up a time map (which uses x and y for coords) while iterating over three (not two) loops. I don’t understand why you are Looping through i – do you have multiple textures defining the same map? I see that i is giving you the limits for the x and y coords for the individual runs, but they should be set to height and width which you set up before you run the Loops - that’s probably explains why your final tile count is off by so much.

Can you explain in your own words what your loops should be doing, eg if you wrote:

for every column x from Zero to my map's height i do the following {
   for every row y from Zero to my map 's width I do the followin {
        I set the field (x,y) to Zero
    }
}

We could quickly Point out that you mixed up height and width.

So if you tell us what you want and what i, x, and y are doing, and what mapData is, we’d probably get this resolved quickly.

my best guess is that the order of your Loops is wrong. You probably want to do domething like this:

for all x from 0 to width-1
  for all y from 0 to height - 1
    create map element for (x,y)
    go through all textures from 0 to i-1 and process Pixel (x,y) of each texture and modify map element (x,y) accordingly

Cheers,
-ch