-
-
Save MerliMejia/26a9a61efc9cea80155ea129f83619d0 to your computer and use it in GitHub Desktop.
2D Tiled Based Map Generator For Unity3D
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
This is a humble approach for creating a random map generator for my game. | |
Please notice that I did not try my best here and this could definitely be way better... | |
I just wanted to have some fun while creating a random map generator. | |
*/ | |
using System.Collections.Generic; | |
using UnityEngine; | |
using UnityEngine.Tilemaps; | |
//What kind of "point or tile" it is. | |
//A Point represents a single square or tile. | |
//It starts at 1 because 0 it's the very first tile layer or "dirt". | |
public enum PointType | |
{ | |
rock1 = 1, | |
rock2, | |
tree1, | |
tree2, | |
} | |
//Represents a single tile or "square". | |
[System.Serializable] | |
public class Square | |
{ | |
//What kind of obstacle it is. | |
public Obstacles obstacle; | |
//How much of it will be drawn. | |
public int maxCount; | |
} | |
public class MapGenerator : MonoBehaviour | |
{ | |
//Reference to the tilemap in which we're drawing. | |
public Tilemap tilemap; | |
//So I can work with different configurations. | |
public List<Square> obstacles; | |
//I'm using this one because I don't want to lose the "max_count" of obstacles added in the inspector. | |
List<Square> obstaclesToWork; | |
//Map width | |
public int widht; | |
//Map height. | |
public int height; | |
//To save all the generated data and use it later. | |
public int[,] mapData; | |
//Just to know when it should generate stuff. | |
[HideInInspector] | |
public bool isInitialized = false; | |
//This is usefull for getting the obstacle's tile faster. | |
private Dictionary<int, Tile> tileDictionary = new Dictionary<int, Tile>(); | |
//This method shuffles an array of integers. | |
//Not sure if it's the best Suffle approach but it gets the job done. | |
public void Shuffle(System.Random rng, int[,] array) | |
{ | |
for (int i = 0; i < array.GetLength(0); i++) | |
{ | |
for (int a = 0; a < array.GetLength(1); a++) | |
{ | |
int randI = rng.Next(i); | |
int randA = rng.Next(a); | |
int temp = array[i, a]; | |
array[i, a] = array[randI, randA]; | |
array[randI, randA] = temp; | |
} | |
} | |
} | |
//Let's start the process. | |
public void Init() | |
{ | |
//We initialize stuff. | |
mapData = new int[widht, height]; | |
tileDictionary = new Dictionary<int, Tile>(); | |
tilemap.ClearAllTiles(); | |
obstaclesToWork = new List<Square>(); | |
obstacles.ForEach((o) => | |
{ | |
Square s = new Square(); | |
s.obstacle = o.obstacle; | |
s.maxCount = o.maxCount; | |
obstaclesToWork.Add(s); | |
}); | |
//We fill the map with random obstacles. | |
for (int i = 0; i < widht; i++) | |
{ | |
for (int a = 0; a < height; a++) | |
{ | |
//Random point type; | |
int data = Random.Range(1, System.Enum.GetNames(typeof(PointType)).Length + 1); | |
mapData[i, a] = data; | |
} | |
} | |
//We can know how many tiles we need to keep based on the maxCount of each obstacle. | |
int objectsToKeep = 0; | |
foreach (Square s in obstaclesToWork) | |
{ | |
objectsToKeep += s.maxCount; | |
tileDictionary.Add((int)s.obstacle.type, s.obstacle.tile); | |
} | |
//Here we work with the dirt objects. Wich is normally the ground and first layer of tiles. | |
int dirtAdded = 0; | |
int[,] dirtArray = mapData; | |
//We fill the dirt array with... dirt. | |
for (int i = 0; i < mapData.GetLength(0); i++) | |
{ | |
for (int a = 0; a < mapData.GetLength(1); a++) | |
{ | |
if (dirtAdded < mapData.Length - objectsToKeep) | |
{ | |
//But we make sure to not add "dirt" if there's still more obstacles in the maxCount. | |
bool shouldAddDirt = true; | |
foreach (Square square in obstaclesToWork) | |
{ | |
if (mapData[i, a] == (int)square.obstacle.type && square.maxCount > 0) | |
{ | |
square.maxCount--; | |
shouldAddDirt = false; | |
break; | |
} | |
} | |
//Once we have skiped all the obstacles we can add "dirt". | |
if (shouldAddDirt) | |
{ | |
dirtArray[i, a] = 0; | |
dirtAdded++; | |
} | |
} | |
else | |
{ | |
break; | |
} | |
} | |
} | |
//At this point the data have all the dirt and obstacles we need, but only the first positions | |
//Of the array have obstacles and this is a *RANDOM* Map Generator... So we shuffle the data. | |
Shuffle(new System.Random(), dirtArray); | |
//And finally, we pass that random data to our mapData array. | |
mapData = dirtArray; | |
//Now, we use this random data to draw stuff like the tiles in the tilemap. | |
int x = 1; | |
int y = 1; | |
for (int i = 0; i < mapData.GetLength(0); i++) | |
{ | |
y = 0; | |
for (int a = 0; a < mapData.GetLength(1); a++) | |
{ | |
try | |
{ | |
tilemap.SetTile(new Vector3Int(x, y, 0), tileDictionary[mapData[i, a]]); | |
} | |
catch (System.Exception) | |
{ | |
} | |
y++; | |
} | |
x++; | |
} | |
isInitialized = true; | |
} | |
//To help me visualize stuff in the development process. | |
private void OnDrawGizmos() | |
{ | |
if (isInitialized) | |
{ | |
int x = 1; | |
int y = 1; | |
for (int i = 0; i < widht; i++) | |
{ | |
y = 0; | |
for (int a = 0; a < height; a++) | |
{ | |
int point = mapData[i, a]; | |
DrawPoint(new Vector3(x, y), (PointType)point); | |
y++; | |
} | |
x++; | |
} | |
} | |
} | |
void DrawPoint(Vector3 position, PointType type) | |
{ | |
if (type == 0) | |
{ | |
Gizmos.color = Color.yellow; | |
} | |
if (type == PointType.rock1 || type == PointType.rock2) | |
{ | |
Gizmos.color = Color.black; | |
} | |
if (type == PointType.tree2 || type == PointType.tree1) | |
{ | |
Gizmos.color = Color.green; | |
} | |
Gizmos.DrawSphere(position, 0.1f); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Collections; | |
using System.Collections.Generic; | |
using UnityEngine; | |
using UnityEditor; | |
[CustomEditor(typeof(MapGenerator))] | |
[CanEditMultipleObjects] | |
public class MapGeneratorEditor : Editor | |
{ | |
MapGenerator map; | |
private void OnEnable() | |
{ | |
map = (MapGenerator)target; | |
map.isInitialized = false; | |
} | |
public override void OnInspectorGUI() | |
{ | |
base.OnInspectorGUI(); | |
if(GUILayout.Button("INIT DATA")) | |
{ | |
map.Init(); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Collections; | |
using System.Collections.Generic; | |
using UnityEngine; | |
using UnityEngine.Tilemaps; | |
[CreateAssetMenu(fileName = "Obstacles", menuName = "Obstacles", order = 1)] | |
public class Obstacles : ScriptableObject | |
{ | |
public PointType type; | |
public Tile tile; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment