- Home /
C# GameObjects Instantiate Into Each Other Issue
I have this script that randomly generates prefabs within a 2D box collider. However I've noticed that sometimes the prefabs spawn into each other. Is there anyway I could prevent this from occurring? I'm not really sure where to start since all of the gameobjects spawn at the same time.
using UnityEngine;
using System.Collections;
public class GeneratePrefabsWithinCollider : MonoBehaviour {
public BoxCollider2D playerCollider;
public GameObject[] placeableObjects;
public GameObject currentObject;
public int numberOfObjects;
public void Start () {
for(int i = 0; i < numberOfObjects;i++)
{
for(int j = 0; j < placeableObjects.Length;j++)
{
currentObject = Instantiate(placeableObjects[j],GeneratedPosition(),Quaternion.Euler(0, 0, Random.Range(0f, 360f))) as GameObject;
currentObject.transform.parent = transform;
}
}
}
Vector3 GeneratedPosition()
{
float x,y;
x = UnityEngine.Random.Range(transform.position.x, transform.position.x + GetComponent<Collider2D>().bounds.size.x) - GetComponent<Collider2D>().bounds.extents.x;
y = UnityEngine.Random.Range(transform.position.y, transform.position.y + GetComponent<Collider2D>().bounds.size.y) - GetComponent<Collider2D>().bounds.extents.y;
return new Vector3(x,y,1);
}
void OnTriggerEnter2D(Collider2D other) {
if(other == playerCollider){
for(int i = 0; i < transform.childCount; i++){
if(transform.GetChild(i).gameObject.activeSelf == false){
transform.GetChild(i).gameObject.SetActive(true);
}
}
}
}
void OnTriggerExit2D(Collider2D other) {
if(other == playerCollider){
for(int i = 0; i < transform.childCount; i++){
if(transform.GetChild(i).gameObject.activeSelf == true){
transform.GetChild(i).gameObject.SetActive(false);
}
}
}
}
}
Answer by DiegoSLTS · Aug 08, 2016 at 09:34 PM
They're not instantiated at the same time, they're instantiated one after another. You can check if an object overlaps any of the created objects, move it to another random position and check again, and repeat until it's in a good position. If they have colliders you can use physic to check, or you can make a fast check for distance if the objects are similar. This has a problem, if you instantiate too many objects you might get stuck if there's no valid position, and it's hard to know when that actually happens.
Okay so I've added a script to the instantiated prefabs which checks to see if another gameobject has intersected them and to recalculate their position if so. However the gameobjects are still intersecting each other and some of them are spawning outside of their parent's collider. What am I doing wrong here?
using UnityEngine;
using System.Collections;
public class IntersectCheck : $$anonymous$$onoBehaviour {
public BoxCollider2D parentCollider;
// Use this for initialization
void Start () {
parentCollider = transform.parent.GetComponent<BoxCollider2D>();
}
// Update is called once per frame
void OnTriggerEnter2D(Collider2D other)
{
if(GetComponent<BoxCollider2D>().bounds.Intersects(other.bounds)){
transform.position = RecalculatedPosition();
}
}
Vector3 RecalculatedPosition()
{
float x,y;
x = UnityEngine.Random.Range(transform.position.x, transform.position.x + parentCollider.bounds.size.x) - parentCollider.bounds.extents.x;
y = UnityEngine.Random.Range(transform.position.y, transform.position.y + parentCollider.bounds.size.y) - parentCollider.bounds.extents.y;
return new Vector3(x,y,1);
}
}
I doubt "OnTriggerEnter2D" is being called at all, have you debugged that? If you add a Debug.Log line there is anything printed in the console?
It looks weird, you have an OnTriggerEnter3D method but it looks like the object with that script doesn't have a collider. Also, those methods are only called if at least one of the objects that collided has a rigidbody.
Anyway, you don't need that, you can check the intersection right after you create each game object. I'll mix some of your code with pseudocode:
public void Start () {
for(int i = 0; i < numberOfObjects;i++)
{
for(int j = 0; j < placeableObjects.Length;j++)
{
currentObject = Instantiate(placeableObjects[j],Vector3.zero,Quaternion.Euler(0, 0, Random.Range(0f, 360f))) as GameObject;
//keep moving the object until it's in a valid position
do {
move currentObject to a random position;
} while ( !validPosition(currentObject) );
currentObject.transform.parent = transform;
}
}
}
bool validPosition(GameObject current) {
foreach ( GO in already instantiated game object) {
if ( current != GO and current's collider intersects GO's collider)
return false;
}
return true;
}
You're right, one of the instantiated gameobjects was missing a rigidbody and that's why it wasn't being returned.
Your answer
Follow this Question
Related Questions
How to randomly spawn three non repeating gameobjects from an array? 2 Answers
C# 2d Instantiate object randomly around gameobject 1 Answer
What is the best way to instatiate an array of connected GameObjects? 0 Answers
Random instantiate at same frame with each instantiate having unique random direction 1 Answer
instantiate random prefabs based on player camera distance 1 Answer