- Home /
Stopping Instantiated GameObjects overlapping
So i am working on placing 6 large cubes around the map randomly by instantiating them.The system works fine but most of the time they overlap each other which i dont want how would i edit my code to do so using UnityEngine; using System.Collections;
public class SpawnRandom : MonoBehaviour
{
public GameObject[] RadiationZone;
public int amount;
private Vector3 spawnPoint;
void Update()
{
RadiationZone = GameObject.FindGameObjectsWithTag("RadiationZoneLayers");
amount = RadiationZone.Length;
if(amount != 4)
{
InvokeRepeating("SpawnZone", 1, 10f);
}
}
void SpawnZone()
{
spawnPoint.x = Random.Range(-0,500);
spawnPoint.y = 1f;
spawnPoint.z = Random.Range(-0,500);
Instantiate(RadiationZone[UnityEngine.Random.Range(0, RadiationZone.Length - 1)],spawnPoint, Quaternion.identity);
CancelInvoke();
}
}
Answer by Keseren · Jan 07, 2016 at 07:01 PM
Try this, if it does not work then I've probably done some minor mistake. The idea should atleast work.
using UnityEngine;
using UnityEditor;
using System.Collections;
using System.Collections.Generic;
public class SpawnRandom : MonoBehaviour {
public GameObject[] RadiationZone;
public int amount;
private Vector3 spawnPoint;
float SizeofCubeWidth;
float SizeofCubeLength;
List<Vector3> SpotsTaken = new List<Vector3>();
void Update() {
RadiationZone = GameObject.FindGameObjectsWithTag("RadiationZoneLayers");
amount = RadiationZone.Length;
if (amount != 4) {
InvokeRepeating("SpawnZone", 1, 10f);
}
}
void SpawnZone() {
spawnPoint.x = Random.Range(-0, 500);
spawnPoint.y = 1f;
spawnPoint.z = Random.Range(-0, 500);
SizeofCubeWidth = transform.localScale.x;
SizeofCubeLength = transform.localScale.z;
foreach (Vector3 SpotTaken in SpotsTaken) {
if (spawnPoint.x >= SpotTaken.x - SizeofCubeWidth && spawnPoint.x <= SpotTaken.x + SizeofCubeWidth) {
if (spawnPoint.z >= SpotTaken.z - SizeofCubeLength && spawnPoint.z <= SpotTaken.z + SizeofCubeLength) {
SpawnZone(); //If the width or length is near another one of these objects, then it tries again
return;
}
}
}
SpotsTaken.Add(spawnPoint);
Instantiate(RadiationZone[UnityEngine.Random.Range(0, RadiationZone.Length - 1)], spawnPoint, Quaternion.identity);
CancelInvoke();
}
}
If the sizeofcubewidth or length is wrong, then change the values I've written. Maybe you can make it into some kind of loop, your choice.
Answer by yelman · Jan 07, 2016 at 02:44 PM
Using FindGameObjectsWithTag in update is a bad idea. Cache them upon instantiation.
Regarding your question, there are multiple ways to make sure the objects don't overlap: -Use Physics.OverlapSphere from the instantiated object to make sure it doesn't overlap with any other cube For example:
GameObject go = Instantiate(RadiationZone[UnityEngine.Random.Range(0, RadiationZone.Length - 1)], spawnPoint, Quaternion.identity) as GameObject;
Physics.OverlapSphere(go.transform.position, yourObjectSize)
-Map your scene using a grid of your object size (assuming the cubes are of the same size) than check if the grid slot is occupied before placing object:
private const int SIZE = 10;
private const float GRID_TO_WORLD = 1;
private float m_cubeSize = 1.0f;
private int[,] m_grid = new int[SIZE, SIZE];
private void Start()
{
// Clean grid
for(int i = 0; i < m_grid.GetUpperBound(0); i++)
{
for(int j = 0; j < m_grid.GetUpperBound(1); j++)
{
m_grid[i, j] = 0;
}
}
}
private void Spawn()
{
// Extremely naive technique, will cause an infinite loop if the grid is full
// As optimization, you can create a grid of Lists and than remove elements from it upon adding an item (removes the search)
int x = -1;
int y = -1;
do
{
x = UnityEngine.Random.Range(0, SIZE);
y = UnityEngine.Random.Range(0, SIZE);
}
while(m_grid[x, y] == 1);
Vector3 spawnPoint = new Vector3(x * GRID_TO_WORLD, y * GRID_TO_WORLD);
GameObject go = Instantiate(RadiationZone[UnityEngine.Random.Range(0, RadiationZone.Length - 1)], spawnPoint, Quaternion.identity) as GameObject;
m_grid[x, y] = 1;
}
Please note the the code snippet hasn't been tested and just provided to get you an idea of what to do rather than being an actual solution.
-Ray cast from the center position of the cube in all directions (4 for 2D, 6 for 3D) the ray size should be half of the cube size.
Answer by svendkiloo · May 10, 2016 at 07:17 AM
I'm not sure how it would work for your problem, @Wintrr, but I was facing a similar situation where I wanted to avoid spawning boxes (or other prefabs) on top of each other. I didn't want to spawn them randomly, so if they would overlap, I would want them to be "pushed" so they didn't. I tried a few different solutions, using the OverlapSphere
like @Keseren and @yelman mentioned, and trying to work out where to push the different objects, to avoid the overlap, but this was difficult, and caused more problems if there were other objects near by.
In the end I just added rigidbodies to the prefabs, froze there location in the y
(up) axis and froze their rotation in their x
and z
axes. This made them pop eachother away, without being launched of or tumbling around. One last thing I did was add quite a bit of drag to them, so they wouldn't slide more away from each other than necessary.
Hope this might be useful to anyone with a similar problem :)
Your answer
Follow this Question
Related Questions
Errors with Random Instantiate Script(Solved) 2 Answers
Randomizing a selection from an array 1 Answer
Random.Range doesn't work 1 Answer