Spawning specified amount of objects randomly without collision.

Hi,

I’m trying to get an enemy to be instantiated at a randomized location (Vector3 on z and x axis) around the object and it must first check whether or not there is another object that will collide with it. However i also want to spawn a set amount of objects no matter what.

My problem is that whenever I try to ensure that the amount of objects spawned is correct with a while/for loop, Unity crashes. I believe this is because the position is being randomized and unity just assumes that it’ll never find a valid position.

Here is my C# Code for the spawning, which causes Unity to freeze:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class SpawnTest : MonoBehaviour
{
    public string[] GroupType = new string[] { "Easy", "Normal", "Hard" };
    [HideInInspector]
    public string groupType;
    [HideInInspector]
    public int num = 0;

    [HideInInspector]
    public int enemiesToSpawn = 0;
    public GameObject[] enemies;

    void Start()
    {
        GenerateGroupType();
        SpawnEnemies();
        Debug.Log("Spawned " + groupType + " pack. \nAt " + transform.position.ToString()
                    + ". " + "\nRoll: " + num.ToString() + "." + "\nPack Size: "
                    + enemiesToSpawn.ToString());
    }

    public void GenerateGroupType() // Decides what group type to spawn
    {
        int num = Random.Range(0, 100);

        if (num <= 80)
        {
            groupType = GroupType[0];
        }
        else if (num > 80 && num <= 95)
        {
            groupType = GroupType[1];
        }
        else if (num > 95 && num <= 100)
        {
            groupType = GroupType[2];
        }
    }

    void SpawnEnemies()
    {
        enemiesToSpawn = Random.Range(6, 10);
        Vector3 spawnPos = new Vector3(Random.Range(-7, 7), 0, Random.Range(-7, 7));

        float radius = 1.0f;
        bool bossNotSpawned = true;

        for (int i = 0; i < enemiesToSpawn; i++)
        {
            spawnPos = new Vector3(Random.Range(-7, 7), 0, Random.Range(-7, 7));

            if (Physics.CheckSphere(spawnPos, radius))
            {
                i--;
            }
            else
            {
                if (groupType == "Hard")
                {
                    if (bossNotSpawned)
                    {
                        Instantiate(enemies[0],
                                    spawnPos,
                                    Quaternion.Euler(new Vector3(0, Random.Range(0, 360), 0)),
                                    gameObject.transform);

                        bossNotSpawned = false;
                    }
                    else
                    {
                        Instantiate(enemies[2],
                                    spawnPos,
                                    Quaternion.Euler(new Vector3(0, Random.Range(0, 360), 0)),
                                    gameObject.transform);
                    }
                }
                else if (groupType == "Normal")
                {
                    Instantiate(enemies[1],
                                spawnPos,
                                Quaternion.Euler(new Vector3(0, Random.Range(0, 360), 0)),
                                gameObject.transform);
                }
                else if (groupType == "Easy")
                {
                    Instantiate(enemies[2],
                                spawnPos,
                                Quaternion.Euler(new Vector3(0, Random.Range(0, 360), 0)),
                                gameObject.transform);
                }
            }
        }
    }
}

This script is attached to an empty Game Object in the scene.

Any help or tips would be appreciated! :slight_smile:

Assuming it doesn’t have a bug in it, then most likely you are running out of places to put the objects.

The way the code above is written, it will endlessly try even when there is no space available.

You can handle this by:

  1. increasing the area in which you can place objects (making the ranges larger over time when things fail for too long)

  2. giving up after a certain number of tries.

So if I choose option 2 I can change the for loop to run for ~100 times as an example and if it has spawned the enemies needed then it must just break the loop?

EDIT: So your method 2 worked for me, however for some reason the Physics.SphereCheck isnt working at some points (I’ve removed the “i–;”), it is spawning the enemy directly inside of another enemy. I’ve only had this occur between two enemies in a group and its not consistently happening though.

I’m not sure what the physics system does if the points are equal… just track the positions of enemies you spawn in your own list and then do your own compare against every enemy you’ve already placed, otherwise you’ll be forever beholden to whatever quirks there are in the physics system.

Oof, was trying to avoid having to save the Vector’s in a random list but I guess its unavoidable. Anyways, appreciate the help! :slight_smile: