Unity3d – In-game Tilemap Editor – Basic Framework

Download the Unity Package

Grid.cs

using UnityEngine;
using System.Collections;
using System.Text;
using System.IO;

public class Grid : MonoBehaviour {

  public GameObject mapParent;
  public GameObject blankTile;
  public GameObject[] tilesToUse;

  public int width;
  public int height;
  public int tileIndex;

  public GameObject[,] grid;
  private int[,] spaces;

  private string fileNameToLoad = "MAP NAME";
  private string mapWidth = "5";
  private string mapHeight = "5";

  void Awake () {
    // Convert string to int
    int.TryParse(mapWidth, out width);
    int.TryParse(mapHeight, out height);
  }

  void Update () {
    // Convert string to int
    int.TryParse(mapWidth, out width);
    int.TryParse(mapHeight, out height);
  }

  // Build a new blank map
  void BuildNewMap () {
    grid = new GameObject[width,height];
    for(int x = 0; x < width; x++) {
      for(int z = 0; z < height; z++) {
        GameObject gridblankTile = (GameObject)Instantiate(blankTile);
        gridblankTile.transform.position = new Vector3(x, 0, z);
        gridblankTile.transform.parent = mapParent.transform;
        gridblankTile.GetComponent<TileType>().xPositionInGrid = x;
        gridblankTile.GetComponent<TileType>().zPositionInGrid = z;
        grid[x,z] = gridblankTile;
      }
    }
  }

  // Save map to file
  void SaveMap () {
    try {
      using(StreamWriter sw = new StreamWriter(Application.dataPath + "\\" + fileNameToLoad + ".txt") ) {
        int x = 0;
        for(int i = 0; i < grid.GetLength(0); i++) {
          for(int j = 0; j < grid.GetLength(1); j++) {

            if(x == width) {
              x = 0;
              sw.WriteLine("");
              sw.Write(grid[i,j].GetComponent<TileType>().tileType + ",");
              
            } else {
              sw.Write(grid[i,j].GetComponent<TileType>().tileType + ",");
              
            }
            x++;
          }
        }
        sw.Close();
      }
    }
    catch(IOException e) {
      Debug.Log(e.Message);
    }
  }

  // Load map from file
  private int[,] LoadMap(string filePath) {
    try {
      using(StreamReader sr = new StreamReader(filePath) ) {
        string input = sr.ReadToEnd();
        string[] lines = input.Split(new[] { '\r', '\n' }, System.StringSplitOptions.RemoveEmptyEntries);
        int[,] spaces = new int[lines.Length, width];
        for(int i = 0; i < lines.Length; i++) {
          string st = lines[i];
          string[] nums = st.Split(new[] {','});
          if(nums.Length != width) {
            Debug.Log("File Split, Filling Array");
          }
          for(int j = 0; j < Mathf.Min(nums.Length, width); j++) {
            int val;
            if(int.TryParse(nums[j], out val) ) {
              spaces[i,j] = val;
            } else {
              spaces[i,j] = 1;
            }
          }
        }
        return spaces;
      }
    }
    catch(IOException e) {
      Debug.Log(e.Message);
    }
    return null;
  }

  // Build map that was loaded from file
  void BuildLoadedMap () {
    for(int i = 0; i < spaces.GetLength(0); i++) {
      for(int j = 0; j < spaces.GetLength(1); j++) {
        GameObject tile;
        switch(spaces[i,j]) {
        case 0:
          tile = Instantiate(blankTile, new Vector3(i, 0, j), Quaternion.identity) as GameObject;
          tile.transform.parent = mapParent.transform;
          break;
        case 1:
          tile = Instantiate(tilesToUse[0], new Vector3(i, 0, j), Quaternion.identity) as GameObject;
          tile.transform.parent = mapParent.transform;
          break;
        case 2:
          tile = Instantiate(tilesToUse[1], new Vector3(i, 0, j), Quaternion.identity) as GameObject;
          tile.transform.parent = mapParent.transform;
          break;
        case 3:
          tile = Instantiate(tilesToUse[2], new Vector3(i, 0, j), Quaternion.identity) as GameObject;
          tile.transform.parent = mapParent.transform;
          break;
        }
      }
    }
  }

  // Clear the map
  void ClearMap () {
    GameObject[] allTiles = GameObject.FindGameObjectsWithTag("Tile");
    if(allTiles.Length > 0) {
      foreach(GameObject tile in allTiles) {
        Destroy(tile);
      }
    }
  }

  // GUI
  void OnGUI () {
    // Menu GUI
    if(GUI.Button(new Rect(10, 10, 100, 50), "New Map") ) {
      ClearMap();
      BuildNewMap();
    }
    if(GUI.Button(new Rect(10, 70, 100, 50), "Load Map") ) {
      ClearMap();
      spaces = LoadMap (Application.dataPath + "\\" + fileNameToLoad + ".txt");
      BuildLoadedMap();
    }
    if(GUI.Button(new Rect(10, 130, 100, 50), "Save Map") ) {
      SaveMap();
    }
    if(GUI.Button(new Rect(10, 200, 100, 50), "Clear Map") ) {
      ClearMap();
    }

    // Tile Selection GUI
    if(GUI.Button(new Rect(Screen.width / 2 - 110, 600, 100, 50), "Red") ) {
      tileIndex = 0;
    }
    if(GUI.Button(new Rect(Screen.width / 2, 600, 100, 50), "Green") ) {
      tileIndex = 1;
    }
    if(GUI.Button(new Rect(Screen.width / 2 + 110, 600, 100, 50), "Blue") ) {
      tileIndex = 2;
    }

    // Map Info Input Fields
    fileNameToLoad = GUI.TextField(new Rect(Screen.width / 2, 10, 200, 50), fileNameToLoad, 25);
    mapWidth = GUI.TextField(new Rect(1000, 10, 25, 25), mapWidth, 2);
    mapHeight = GUI.TextField(new Rect(1000, 35, 25, 25), mapHeight, 2);

    // Map Info Labels
    GUI.Label(new Rect(1050, 10, 100, 25), "Width");
    GUI.Label(new Rect(1050, 35, 100, 25), "Height");
  }
}

TileType.cs

using UnityEngine;
using System.Collections;

public class TileType : MonoBehaviour {
  
  public int xPositionInGrid;
  public int zPositionInGrid;
  public int tileType;
}

ChangeTile.cs

using UnityEngine;
using System.Collections;

public class ChangeTile : MonoBehaviour {

  private Grid gridScript;
  private GameObject mapParent;
  private TileType tileTypeScript;
  
  void Awake () {
    gridScript = GameObject.FindGameObjectWithTag("Grid").GetComponent<Grid>();
    mapParent = GameObject.FindGameObjectWithTag("MapParent");
    tileTypeScript = GetComponent<TileType>();
  }

  // Called when mouse down registers on this gameObject
  void OnMouseDown () {
    // Instantiate the new tile int he same position as this tile
    GameObject newTile = Instantiate(gridScript.tilesToUse[gridScript.tileIndex].gameObject, transform.position, Quaternion.identity) as GameObject;
    // Set the parent
    newTile.transform.parent = mapParent.transform;
    // Get reference to the new tile's script
    TileType newTileScript = newTile.GetComponent<TileType>();
    // Set new tile's positions based on this gameObject's position
    newTileScript.xPositionInGrid = this.tileTypeScript.xPositionInGrid;
    newTileScript.zPositionInGrid = this.tileTypeScript.zPositionInGrid;
    // Update the grid array with the new tile
    gridScript.grid[newTileScript.xPositionInGrid, newTileScript.zPositionInGrid] = newTile;
    // Destroy this gameObject
    Destroy(this.gameObject);
  }
}