I am currently in the early stages of working on a 2D turn-based strategy game (think Fire Emblem). I’m creating my own tile map editor to be used in the Unity editor, here is the code for the map so far:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
[System.Serializable]
public class Map : MonoBehaviour {
public Vector2 mapDimensions = new Vector2(5, 5); //The width and height of the map in tiles.
public Vector2 tileSize = new Vector2 (32, 32); //The width and height of a single tile in pixels.
public Color gridColour = Color.green;
public Color SelectionColour = Color.red;
private GameObject tileParent;
private GameObject unitParent;
private Tile mouseOverTile;
[SerializeField]
private Tile[] tiles = new Tile[0];
private Vector2 _currentGridDimensions;
public Vector2 currentGridDimensions{
get{ return _currentGridDimensions; }
}
void OnEnable(){
InputManager.MousePositonBroadcast += CheckMouseOverTile;
}
void OnDisable(){
InputManager.MousePositonBroadcast -= CheckMouseOverTile;
}
public void CreateTileParent(){
if (tileParent != null) {
return;
}
tileParent = new GameObject ();
tileParent.name = "Tiles";
tileParent.transform.SetParent (transform);
}
public void ConfigureUnitParent (Unit unit){
if (unitParent == null) {
unitParent = new GameObject ();
unitParent.name = "Units";
unitParent.transform.SetParent (transform);
}
if(!unit.transform.IsChildOf(transform)){
unit.transform.SetParent (unitParent.transform);
}
}
public void Retile(int xSize, int ySize, GameObject tilePrefab){
var newTileArray = new Tile[xSize * ySize];
int smallestX = xSize < _currentGridDimensions.x ? xSize : (int) _currentGridDimensions.x;
int smallestY = ySize < _currentGridDimensions.y ? ySize : (int) _currentGridDimensions.y;
var newI = 0; //Used to index the new array in the following loop.
var currentI = 0; //Used to index tiles array in the following loop.
var x = 0;
while (newI < smallestY * xSize) {
newTileArray [newI] = tiles [currentI];
newI++;
currentI++;
x++;
if(x >= smallestX){
if (_currentGridDimensions.x < xSize) {
while (x < xSize) {
AddTileToGrid (newTileArray, newI, xSize, tilePrefab);
newI++;
x++;
}
x = 0;
} else {
while (x < _currentGridDimensions.x) {
DestroyImmediate (tiles[currentI].gameObject);
currentI++;
x++;
}
x = 0;
}
}
}
if (tiles.Length < newTileArray.Length) {
for (int i = newI; i < newTileArray.Length; i++) {
AddTileToGrid (newTileArray, i, xSize, tilePrefab);
}
} else {
for (int i = currentI; i < tiles.Length; i++) {
DestroyImmediate (tiles *.gameObject);*
-
}*
-
}*
-
_currentGridDimensions = new Vector2 (xSize, ySize);*
-
tiles = newTileArray;*
-
}*
-
private void AddTileToGrid(Tile grid, int i, int xSize, GameObject tilePrefab){*
-
var x = i % xSize;*
-
var y = i / xSize;*
-
var newTile = Instantiate (tilePrefab);*
-
newTile.name = "Tile ("+x +", "+y+")";*
-
newTile.transform.SetParent (tileParent.transform);*
_ newTile.transform.position = new Vector3 (transform.position.x + x * tileSize.x,_
_ transform.position.y + y * tileSize.y,_
-
newTile.transform.position.z);*
-
var tile = newTile.GetComponent<Tile> ();*
-
tile.mapPosition = new Vector2 (x, y);*
_ grid = newTile.GetComponent();_
* }*
* public Tile GetTile(int x, int y){*
* Debug.Log (“Retrieving Tile”);*
* if (tiles == null || tiles.Length == 0) {*
* return null;*
* }*
return tiles [(int)(y * _currentGridDimensions.y + x)];
* }*
* // Subscribed to EventManager’s MousePositonBroadcast event. Checks to see which of it’s tiles the mouse is over, if any.*
* private void CheckMouseOverTile(Vector3 positon){*
* var x = (int)((positon.x - transform.position.x + tileSize.x / 2) / tileSize.x);*
* var y = (int)((positon.y - transform.position.y + tileSize.y / 2) / tileSize.y);*
* Debug.Log (tiles.Length);*
* Tile newMouseOverTile = null;*
* if (x < mapDimensions.x && x >= 0 && y < mapDimensions.y && y >= 0) {*
newMouseOverTile = tiles [(int)(y * _currentGridDimensions.y + x)].GetComponent();
* }*
* if (newMouseOverTile != mouseOverTile) {*
* mouseOverTile.gameObject.GetComponent ().color = Color.white;*
* mouseOverTile = newMouseOverTile;*
* }*
* else if(newMouseOverTile != null){*
* mouseOverTile.gameObject.GetComponent ().color = Color.blue;*
* }*
* }*
* //Draws the grid for the map.*
* void OnDrawGizmos(){*
* Gizmos.color = gridColour;*
* var cellSize = new Vector3 (tileSize.x, tileSize.y, 1);*
* var startX = transform.position.x;*
* var startY = transform.position.y;*
* for (int x = 0; x < mapDimensions.x; x++) {*
* for (int y = 0; y < mapDimensions.y; y++) {*
_ var xPos = startX + tileSize.x * x;
var yPos = startY + tileSize.y * y;_
* var cellPosition = new Vector3 (xPos, yPos, 1);*
* Gizmos.DrawWireCube (cellPosition, cellSize);*
* }*
* }*
* }*
}
Within the map object I want to store an array of tiles, that will eventually be connected to one another to create a graph for path-finding. The plan is to make that array of tiles (called ‘tiles’ in the above code) changeable in the editor to allow for easy map editing when we come to creating levels, but Unity clears this array when I go to play the game itself, is there any way around this? I have researched and tried multiple approaches, for example - the tiles were originally held in a list, then a two-dimensional array, and now just a one-dimensional array, and I’ve tried things like ‘Serializable’ - but I keep encountering the same problem. Can anyone think of a way I can bring that array of tiles from the unity editor, into the game itself without losing the tiles? Ideally I would like to store the tiles in a list or 2d array like I had I originally planned.