Hey there. So it looks like prefabs do not know their bounds size until they are spawned. So there’s two ways to go about this. Spawn it off screen, then place it, or define the size beforehand in the inspector.
Here are those two solutions. (Note that I changed your hard-coded 7.5 random range for spawning to use the screen bounds. Feel free to change it back if that’s not desired.
Remember your object must have a collider and the LayerMask must contain the layer of the spawned object.
Spawn first, then position:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class Random_Generation : MonoBehaviour {
//private GameObject instantiatedObj; //Holds my "cloned/spawned" objects. Keep for now but is unneeded at the moment
// list of prefabs to spawn
public List<GameObject> spawnableObjects;
//Layer that spawned objects are on
public LayerMask collisionTest;
public GameObject spawnedObject;
// Use this for initialization
void Start() {
//Randomly Spawns Game Objects at set intervals
//This code works!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
InvokeRepeating("randomSpawn", 3.0f, 3.0f); // Kepp this code
}
//Random Generation Method
//This code works!!!!!!!!!!!!!!!!!!!!!!!!!!!
//Errors in overlaping instantiated objects
void randomSpawn() {
//int counter;
//Vector2 randomSpawnPosition = new Vector2(Random.Range(-7.5f, 7.5f), Random.Range(-7.5f, 7.5f)); // Keep this code, TEMP COMMENTED OUT
//Pick the next Prefab randomly to spawn, COMMENTED OUT (DON'T NEED)
//int randomIndex = (int)(Random.value * (spawnableObjects.Count - 1));
// Why -1?????? (DON'T NEED)
// -1 because an index starts at 0. If you have a count of 10, the final index will be 9.
//GameObject prefabToSpawn = spawnableObjects[randomIndex]; //COMMENTED OUT (DON'T NEED)
// Spawns my object off screen
GameObject newObject = (GameObject)Instantiate(spawnedObject, new Vector3(-100, -100, -100), Quaternion.identity); //Keep this code, changed spawnedObject to prefabToSpawn for this test
//Choose a position that doesn't overlap on the specified layermask
Vector2 randomSpawnPosition = getValidSpawnLocation(newObject);
if(randomSpawnPosition == Vector2.zero) {
Debug.Log("no more room!");
Destroy(newObject);
} else {
newObject.transform.position = randomSpawnPosition;
}
//Below code currently seems to be unneeded at the moment but keep it just in case. Not sure why I needed it in the first place.
//instantiatedObj = (GameObject)Instantiate(spawnedObject, randomSpawnPosition, Quaternion.identity); // Keep this code
} //End of randomSpawn()
private Vector2 getValidSpawnLocation(GameObject go) {
Collider2D objectCollider = go.GetComponent<Collider2D>();// Creates a variable called objectCollider and assigns the 2D Collider Component from the Game Object that is being passed into the Method.
Vector3 newPosition = Vector2.zero; //sets the new postion to (0,0,0). Changed to Vector 3 3 in my code because of the objectCollider.bounds.extents which is a Vector 3
bool validPosition = false; //Boolian for getting out of the Do/While loop
// failsafe to prevent infinite loops
int failureLimit = 100;
int fails = 0;
do {
// get the bottom left corner of the screen in world space
Vector2 screenMin = Camera.main.ViewportToWorldPoint(Vector3.zero); // Vector3.zero = same as new Vector3(0,0,0)
// get the top right corner of the screen in world space
Vector2 screenMax = Camera.main.ViewportToWorldPoint(Vector3.one); // Vector3.one = same as new Vector3(1,1,1)
// get a random position for the X and Y positional coordanintes on screen
newPosition.x = Random.Range(screenMin.x, screenMax.x);
newPosition.y = Random.Range(screenMin.y, screenMax.y);
// these next two values are passed to the "OverlapAreaAll" function to tell it
// what area to check for collisions. They are opposite corners of a square.
// we add and subtract the object collider's half-width (extents) from the new position
// to get the opposing corners of the square area that the object will take up
// at the new position
Vector3 min = newPosition - objectCollider.bounds.extents;
Vector3 max = newPosition + objectCollider.bounds.extents;
// !!!!!!!!!!!!!!!!CHECKS FOR OVERLAPING!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Collider2D[] overlapObjects = Physics2D.OverlapAreaAll(min, max, collisionTest);
//if it does not overlap any objects in the layermask
if(overlapObjects.Length == 0) {
Debug.Log("good");
//break out of the Do/While loop
validPosition = true;
// reset the failsafe
fails = 0;
} else {
Debug.Log("Overlapping has occured");
fails++;
}
// added a fail-safe to prevent infinite looping if there is no space left
} while(!validPosition && fails < failureLimit);
return newPosition;
}
} // End of Random_Generation class
Define the size in the inspector:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class Random_Generation : MonoBehaviour {
//private GameObject instantiatedObj; //Holds my "cloned/spawned" objects. Keep for now but is unneeded at the moment
// list of prefabs to spawn
public List<GameObject> spawnableObjects;
//Layer that spawned objects are on
public LayerMask collisionTest;
public GameObject spawnedObject;
public Vector2 spawnedObjectSize;
private Vector2 spawnedObjectHalfSize;
// Use this for initialization
void Start() {
spawnedObjectHalfSize = spawnedObjectSize * 0.5f;
//Randomly Spawns Game Objects at set intervals
//This code works!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
InvokeRepeating("randomSpawn", 3.0f, 3.0f); // Kepp this code
}
//Random Generation Method
//This code works!!!!!!!!!!!!!!!!!!!!!!!!!!!
//Errors in overlaping instantiated objects
void randomSpawn() {
//int counter;
//Vector2 randomSpawnPosition = new Vector2(Random.Range(-7.5f, 7.5f), Random.Range(-7.5f, 7.5f)); // Keep this code, TEMP COMMENTED OUT
//Pick the next Prefab randomly to spawn, COMMENTED OUT (DON'T NEED)
//int randomIndex = (int)(Random.value * (spawnableObjects.Count - 1));
// Why -1?????? (DON'T NEED)
// -1 because an index starts at 0. If you have a count of 10, the final index will be 9.
//GameObject prefabToSpawn = spawnableObjects[randomIndex]; //COMMENTED OUT (DON'T NEED)
//Choose a position that doesn't overlap on the specified layermask
Vector2 randomSpawnPosition = getValidSpawnLocation(spawnedObject);
if(randomSpawnPosition == Vector2.zero) {
Debug.Log("no more room!");
} else {
// Spawns my object
Instantiate(spawnedObject, randomSpawnPosition, Quaternion.identity); //Keep this code, changed spawnedObject to prefabToSpawn for this test
}
//Below code currently seems to be unneeded at the moment but keep it just in case. Not sure why I needed it in the first place.
//instantiatedObj = (GameObject)Instantiate(spawnedObject, randomSpawnPosition, Quaternion.identity); // Keep this code
} //End of randomSpawn()
private Vector2 getValidSpawnLocation(GameObject go) {
Collider2D objectCollider = go.GetComponent<Collider2D>();// Creates a variable called objectCollider and assigns the 2D Collider Component from the Game Object that is being passed into the Method.
Vector3 newPosition = Vector2.zero; //sets the new postion to (0,0,0). Changed to Vector 3 3 in my code because of the objectCollider.bounds.extents which is a Vector 3
bool validPosition = false; //Boolian for getting out of the Do/While loop
// failsafe to prevent infinite loops
int failureLimit = 100;
int fails = 0;
do {
// get the bottom left corner of the screen in world space
Vector2 screenMin = Camera.main.ViewportToWorldPoint(Vector3.zero); // Vector3.zero = same as new Vector3(0,0,0)
// get the top right corner of the screen in world space
Vector2 screenMax = Camera.main.ViewportToWorldPoint(Vector3.one); // Vector3.one = same as new Vector3(1,1,1)
// get a random position for the X and Y positional coordanintes on screen
newPosition.x = Random.Range(screenMin.x, screenMax.x);
newPosition.y = Random.Range(screenMin.y, screenMax.y);
// these next two values are passed to the "OverlapAreaAll" function to tell it
// what area to check for collisions. They are opposite corners of a square.
// we add and subtract the object collider's half-width (extents) from the new position
// to get the opposing corners of the square area that the object will take up
// at the new position
Vector3 min = newPosition - (Vector3)spawnedObjectHalfSize;
Vector3 max = newPosition + (Vector3)spawnedObjectHalfSize;
// !!!!!!!!!!!!!!!!CHECKS FOR OVERLAPING!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Collider2D[] overlapObjects = Physics2D.OverlapAreaAll(min, max, collisionTest);
//if it does not overlap any objects in the layermask
if(overlapObjects.Length == 0) {
Debug.Log("good");
//break out of the Do/While loop
validPosition = true;
// reset the failsafe
fails = 0;
} else {
Debug.Log("Overlapping has occured");
fails++;
}
// added a fail-safe to prevent infinite looping if there is no space left
} while(!validPosition && fails < failureLimit);
return newPosition;
}
} // End of Random_Generation class