- Home /
Spawning prefabs randomly on top of existing tiles
Good day everyone!
I'm currently in the process of building a 2D Game, and as for my next step I'd like to randomly spawn collectable gems (prefabs) on top of my tiles for the player to collect.
My tilemap is generated at runtime.
I've tried various solutions however I can't seem to get it quite right. I know that I'm supposed to get the positions of the tiles and check whether the tile below is empty or not, however I'm not sure how to implement this, and I'd really appreciate the help! Thank you. :)
Answer by nursedayuksel · Nov 10, 2020 at 09:03 PM
Here's my code for generating the tilemap incase anyone would like to see it.
void GenerateMap()
{
float seed = UnityEngine.Random.Range(.1f, 1f);
mapArray = GenerateArray(terrainWidth, terrainHeight, true);
RenderMap(PerlinNoiseSmooth(mapArray, seed, 3), tilemap, tile);
}
public static int[,] GenerateArray(int width, int height, bool empty)
{
int[,] map = new int[width, height];
for (int x = 0; x < map.GetUpperBound(0); x++)
{
for (int y = 0; y < map.GetUpperBound(1); y++)
{
if (empty)
{
map[x, y] = 0;
}
else
{
map[x, y] = 1;
}
}
}
return map;
}
public static void RenderMap(int[,] map, Tilemap tilemap, TileBase tile)
{
//Clear the map (ensures we dont overlap)
tilemap.ClearAllTiles();
//Loop through the width of the map
for (int x = 0; x < map.GetUpperBound(0); x++)
{
//Loop through the height of the map
for (int y = 0; y < map.GetUpperBound(1); y++)
{
// 1 = tile, 0 = no tile
if (map[x, y] == 1)
{
tilemap.SetTile(new Vector3Int(x, y, 0), tile);
}
}
}
}
public static void UpdateMap(int[,] map, Tilemap tilemap) //Takes in our map and tilemap, setting null tiles where needed
{
for (int x = 0; x < map.GetUpperBound(0); x++)
{
for (int y = 0; y < map.GetUpperBound(1); y++)
{
//We are only going to update the map, rather than rendering again
//This is because it uses less resources to update tiles to null
//As opposed to re-drawing every single tile (and collision data)
if (map[x, y] == 0)
{
tilemap.SetTile(new Vector3Int(x, y, 0), null);
}
}
}
}
public static int[,] PerlinNoise(int[,] map, float seed)
{
int newPoint;
//Used to reduced the position of the Perlin point
float reduction = 0.5f;
//Create the Perlin
for (int x = 0; x < map.GetUpperBound(0); x++)
{
newPoint = Mathf.FloorToInt((Mathf.PerlinNoise(x, seed) - reduction) * map.GetUpperBound(1));
//Make sure the noise starts near the halfway point of the height
newPoint += (map.GetUpperBound(1) / 2);
for (int y = newPoint; y >= 0; y--)
{
map[x, y] = 1;
}
}
return map;
}
public static int[,] PerlinNoiseSmooth(int[,] map, float seed, int interval)
{
//Smooth the noise and store it in the int array
if (interval > 1)
{
int newPoint, points;
//Used to reduced the position of the Perlin point
float reduction = 0.5f;
//Used in the smoothing process
Vector2Int currentPos, lastPos;
//The corresponding points of the smoothing. One list for x and one for y
List<int> noiseX = new List<int>();
List<int> noiseY = new List<int>();
//Generate the noise
for (int x = 0; x < map.GetUpperBound(0); x += interval)
{
newPoint = Mathf.FloorToInt((Mathf.PerlinNoise(x, (seed * reduction))) * map.GetUpperBound(1));
noiseY.Add(newPoint);
noiseX.Add(x);
}
points = noiseY.Count;
//Start at 1 so we have a previous position already
for (int i = 1; i < points; i++)
{
//Get the current position
currentPos = new Vector2Int(noiseX[i], noiseY[i]);
//Also get the last position
lastPos = new Vector2Int(noiseX[i - 1], noiseY[i - 1]);
//Find the difference between the two
Vector2 diff = currentPos - lastPos;
//Set up what the height change value will be
float heightChange = diff.y / interval;
//Determine the current height
float currHeight = lastPos.y;
//Work our way through from the last x to the current x
for (int x = lastPos.x; x < currentPos.x; x++)
{
for (int y = Mathf.FloorToInt(currHeight); y > 0; y--)
{
map[x, y] = 1;
}
currHeight += heightChange;
}
}
}
else
{
//Defaults to a normal Perlin gen
map = PerlinNoise(map, seed);
}
return map;
}
}
Your answer
Follow this Question
Related Questions
Spawning a specific Tile in a random position a certain distance from the player character 1 Answer
Destroy tile at impact (similar to Broforce)? 1 Answer
Random Map generation like Temple run,Random Map generation like Temple Run. 0 Answers
How to make enemy prefab spawn at random times between 1.0f to 10.0f. 1 Answer
Trouble with tilemaps as prefabs for 2D plattformer 1 Answer