- Home /
When spawning to a grid, how to only spawn one object next to another?
I'm trying to spawn cubes on a grid. At the moment the yellow and blue cubes spawn randomely while the pink cube spawns at the center. I'm trying to work out how I could have the blue cubes only spawn next to yellow cubes?
I think maybe I need to save the yellow cube coordinates to a queue when they're spawned and then somehow check that the blue coords are equal to those yellow ones plus or minus one but to be honest I've no idea how to move forward with this.
Any help would be much appreciated.
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class MapGenerator : MonoBehaviour {
public Transform tilePrefab;
public Transform obstaclePrefab;
public Transform obstacle2Prefab;
public Transform obstacle3Prefab;
public Vector2 mapSize;
[Range(0,1)]
public float outlinePercent;
[Range(0,1)]
public float obstaclePercent;
public float tileSize;
public int obstacle2Count = 5;
public int obstacle3Count = 5;
List<Coord> allTileCoords;
Queue<Coord> shuffledTileCoords;
public int seed = 10;
Coord mapCentre;
void Start() {
GenerateMap ();
}
public void GenerateMap() {
allTileCoords = new List<Coord> ();
for (int x = 0; x < mapSize.x; x ++) {
for (int y = 0; y < mapSize.y; y ++) {
allTileCoords.Add(new Coord(x,y));
}
}
shuffledTileCoords = new Queue<Coord> (Utility.ShuffleArray (allTileCoords.ToArray (), seed));
mapCentre = new Coord ((int)mapSize.x / 2, (int)mapSize.y / 2);
string holderName = "Generated Map";
if (transform.Find (holderName)) {
DestroyImmediate (transform.Find (holderName).gameObject);
}
Transform mapHolder = new GameObject (holderName).transform;
mapHolder.parent = transform;
for (int x = 0; x < mapSize.x; x ++) {
for (int y = 0; y < mapSize.y; y ++) {
Vector3 tilePosition = CoordToPosition(x,y);
Transform newTile = Instantiate (tilePrefab, tilePosition, Quaternion.Euler (Vector3.right * 90)) as Transform;
newTile.localScale = Vector3.one * (1 - outlinePercent) * tileSize;
newTile.parent = mapHolder;
}
}
bool[,] obstacleMap = new bool[(int)mapSize.x,(int)mapSize.y];
int obstacleCount = (int)(mapSize.x * mapSize.y * obstaclePercent);
int currentObstacleCount = 0;
//spawn pink cube
for (int i =0; i < obstacleCount; i ++) {
Coord randomCoord = GetRandomCoord();
obstacleMap[randomCoord.x,randomCoord.y] = true;
currentObstacleCount ++;
if (randomCoord == mapCentre) {
Vector3 obstaclePosition = CoordToPosition(randomCoord.x,randomCoord.y);
Transform newObstacle = Instantiate(obstaclePrefab, obstaclePosition + Vector3.up * .5f, Quaternion.identity) as Transform;
newObstacle.parent = mapHolder;
newObstacle.localScale = Vector3.one * (1 - outlinePercent) * tileSize;
}
else {
obstacleMap[randomCoord.x,randomCoord.y] = false;
currentObstacleCount --;
}
}
//spawn yellow cube
for (int i =0; i < obstacle2Count; i ++) {
Coord randomCoord = GetRandomCoord();
Vector3 obstaclePosition = CoordToPosition(randomCoord.x,randomCoord.y);
Transform newObstacle = Instantiate(obstacle2Prefab, obstaclePosition + Vector3.up * .5f, Quaternion.identity) as Transform;
newObstacle.parent = mapHolder;
}
//spawn blue cube
for (int i =0; i < obstacle3Count; i ++) {
//only spawn blue cubes next to yellow cubes
//if (randomCoord == mapCentre) {
Coord randomCoord = GetRandomCoord();
Vector3 obstaclePosition = CoordToPosition(randomCoord.x,randomCoord.y);
Transform newObstacle = Instantiate(obstacle3Prefab, obstaclePosition + Vector3.up * .5f, Quaternion.identity) as Transform;
newObstacle.parent = mapHolder;
}
}
bool MapIsFullyAccessible(bool[,] obstacleMap, int currentObstacleCount) {
bool[,] mapFlags = new bool[obstacleMap.GetLength(0),obstacleMap.GetLength(1)];
Queue<Coord> queue = new Queue<Coord> ();
queue.Enqueue (mapCentre);
mapFlags [mapCentre.x, mapCentre.y] = true;
int accessibleTileCount = 1;
while (queue.Count > 0) {
Coord tile = queue.Dequeue();
for (int x = -1; x <= 1; x ++) {
for (int y = -1; y <= 1; y ++) {
int neighbourX = tile.x + x;
int neighbourY = tile.y + y;
if (x == 0 || y == 0) {
if (neighbourX >= 0 && neighbourX < obstacleMap.GetLength(0) && neighbourY >= 0 && neighbourY < obstacleMap.GetLength(1)) {
if (!mapFlags[neighbourX,neighbourY] && !obstacleMap[neighbourX,neighbourY]) {
mapFlags[neighbourX,neighbourY] = true;
queue.Enqueue(new Coord(neighbourX,neighbourY));
accessibleTileCount ++;
}
}
}
}
}
}
int targetAccessibleTileCount = (int)(mapSize.x * mapSize.y - currentObstacleCount);
return targetAccessibleTileCount == accessibleTileCount;
}
Vector3 CoordToPosition(int x, int y) {
return new Vector3 (-mapSize.x / 2 + 0.5f + x, 0, -mapSize.y / 2 + 0.5f + y) * tileSize;
}
public Coord GetRandomCoord() {
Coord randomCoord = shuffledTileCoords.Dequeue ();
shuffledTileCoords.Enqueue (randomCoord);
return randomCoord;
}
public struct Coord {
public int x;
public int y;
public Coord(int _x, int _y) {
x = _x;
y = _y;
}
public static bool operator ==(Coord c1, Coord c2) {
return c1.x == c2.x && c1.y == c2.y;
}
public static bool operator !=(Coord c1, Coord c2) {
return !(c1 == c2);
}
}
}
Answer by Kaart · May 05, 2020 at 12:16 AM
You can use a list to save the positions of the yellow cubes.
List<Vector3> yellowCubePositions = new List<Vector3>();
Fill the list in your spawn yellow cube code.
//spawn yellow cube
List<Vector3> yellowCubePositions = new List<Vector3>();
for (int i = 0; i < obstacle2Count; i++)
{
Coord randomCoord = GetRandomCoord();
Vector3 obstaclePosition = CoordToPosition(randomCoord.x, randomCoord.y);
Transform newObstacle = Instantiate(obstacle2Prefab, obstaclePosition + Vector3.up * .5f, Quaternion.identity) as Transform;
newObstacle.parent = mapHolder;
yellowCubePositions.Add(obstaclePosition);
}
Add some code to get the position of a random yellow cube.
// Returns the position of a yellow cube.
private Vector3 GetRandomYellowCubePosition()
{
return yellowCubePositions[Random.Range(0, yellowCubePositions.Count - 1)];
}
Get the position of a random yellow cube in your spawn blue cube code. Add some distance to prevent it spawning inside the yellow cube.
//spawn blue cube
for (int i = 0; i < obstacle3Count; i++)
{
//only spawn blue cubes next to yellow cubes
// TODO: Add or subtract some distance to prevent to blue
// cube spawning inside the yellow cube.
Vector3 obstaclePosition = GetRandomYellowCubePosition();
Transform newObstacle = Instantiate(obstacle3Prefab, obstaclePosition + Vector3.up * .5f, Quaternion.identity) as Transform;
newObstacle.parent = mapHolder;
}
Your answer
Follow this Question
Related Questions
Multiple Cars not working 1 Answer
Distribute terrain in zones 3 Answers
2d spawn across screen 1 Answer
Spawning A Grid Of Cubes 2 Answers
Trying to make a spawning enemy code 1 Answer