Hi,
This question can be broken up into different steps. All within a modified for loop:
for (int i = 0; i < NumberOfSpawns; i = i) { /* Code Below Goes In Here*/ }
Note that we are not doing i++. Because we want to manually increase the count if we had a successful spawn.
Within the for loop we need a few steps:
Step 1: The first is to find a random spawning position.
This can be done with the Random.Range() function mentioned above. Use the following Code:
// Get position of Circle
float circleParam = 2 * Mathf.PI * Random.Range (0.0f, 1.0f );
// Select Start Position
Vector3 startPos = new Vector3 (
radius * Mathf.Sin (circleParam),
0.5f, /* Spawn above ground */
radius * Mathf.Cos (circleParam )
);
Step 2: Check for Collision
In this step use SpherecastAll to check for collision. below is a written function that checks for collision within a certain radius.
// Inside for loop:
bool canSpawn = !isCollision (prefabRadius, startPos);
// The function
bool isCollision (radius, position) {
// Create new ray
Ray ray = new Ray(position, Vector3.up);
// Create Raycast hits array
RaycastHit[] hits;
// Do the raycast
hits = Physics.SphereCastAll(ray, radius, 0f); //Can change 0f to prefabHeight / 2.1f if you need to check height
return hits.length > 0;
}
Step 3: Spawn or continue to next step
No that we know if it will collide with an object or not we can write the end of the for loop here:
if (canSpawn) { // you can spawn it so do it
// Instantiate the object
GameObject obj = Instantiate (prefab, startPosition, Quaternion.identity * Quaternion.Euler (new Vector3(0, Range.Random(0, 359), 0))) as GameObject;
// IMPORTANT: Increase the loop counter or you will get stuck in the loop
i++;
} else
continue; // Step to the next iteration without increasing i
All of this will ensure that you spawn the selected amount of objects and that they do not collide.
FINALLY: If you want them to despawn when out of range then keep track off all the objects in a list and use this function below in the LateUpdate function:
void LateUpdate () {
for (int i = 0; i < enemyList.Count; i = i) {
// Get the distance between them
float distanceFromPlayer = Vector3.Distance (playerPosition, enemyList*.transform.position);*
// Remove if greater than radius
if (distanceFromPlayer > radius) {
// remove from list
enemyList.Remove (enemyList*);*
} else {
// No Object Removed so increase i
i++;
}
}
}