Help on building a script to spawn gameObjects in random different locations in world

Hi, i’m new to the comunity, i’m building a tension game like Slender and Survivors, which i want to be multiplayer at the end of this job, and now, i’ve learned the basics of scripting, made almost all by myself the scripts for the main menu, the pause menu, followed the great Alucard Guides to make the AI for my creature, i’ve setup my world and so on…

These week, one of my friends told me that i won’t be able to play my own game with other people because…well, i’ll know the exact location of the objetcs to get, at least, in the easy way, and i recognize that’s true…but all the work this game is taking to me…,¡i want to enjoy it too!, so i thought that i’ll need to make the objects that players need to collect during the game…spawn in random locations at the beggining of the level, and then i thought that if i want the gameObjects to spawn in any location of my world…that would be very very tricky, because they can spawn below or above the terrain, too high or to low, and trying to make the code to spawn the gameObjects based on certain rules…, i think that would be difficult, and as i said, i’m a noob to this work, so i planned a second option.

Basically i wanted to ask you for a way to make my gameObjects to spawn in random locations, but those locations, to be presets, i mean, lets say…a list of 40 or 50 different places in my scene, and then, make my gameObjects to be moved and enabled to those randomly selected places at the start of the level.

That would save me from staying away, so once i finish my game, i’ll be available to play it almost without making cheat, and this feature would make my game to be slightly diffetent every time the player enters it.

So…any ideas please? what functions and variables would i need? what steps do i have to take?

Thanks in advance, and have a nice day!:slight_smile:

You already got all the details in your mind and it’s actually not too hard to bring that into the game. The easiest way is to just create those 40 or 50 different places where your objects might spawn. Collect those in an array, or a list or any other type of collection. Get a random transform of this array, get it’s position and use it to spawn your objects. Easy as that.

So as I said, place gameObjects where the spawn points should be. Create some kind of spawning manager and use some script like this:

// drop your spawn points in this array in the inspector
public Transform[] possibleSpawnPositions;

// drop a gameObject (preferably a prefab) here in the inspector
public GameObject objectTypeToSpawn;

// call this function whenever you want to spawn a new object at a random position
public void SpawnNewObject() {
	Transform spawnPointReference = GetSpawnPointReference();
	Transform newObject = Instantiate(objectTypeToSpawn, spawnPointReference.position, spawnPointReference.rotation) as Transform;
	
	// do any other stuff with newObject here...
}

// function to get a random transform from the list of possible spawn points
public Transform GetSpawnPointReference() {
	int randomIndex = Random.Range(0, possibleSpawnPositions.Length);
	return possibleSpawnPositions[randomIndex];
}
2 Likes

Hey friend, thanks for the reply!, but i forgot to mention that…i know the basics, but only for Javascripts, unfortunately i can’t get into C# yet, would you please transform it? i tried a couple of times to understand the error that unity thrhows when revising the initial code, but, i don’t understand it enough, sorry.

I translated it to JavaScript for you. You still of course will have to call the functions somehow. I would suggest a boolean such as spawnEnemies. And a simple check if its true or not, if true spawn random enemies. Then you can all ways set it to true when you want by any script by making it a static var. Throw it in update and you should be good to go!

Just be sure to call GetSpawnPointReference() first (it will return a Vector3), since SpawnNewObject() needs that random position. Hope that helps.

// drop your spawn points in this array in the inspector

var  possibleSpawnPositions: Transform[];

// drop a gameObject (preferably a prefab) here in the inspector

var  objectTypeToSpawn: GameObject;

 

// call this function whenever you want to spawn a new object at a random position

function SpawnNewObject() 
{
     var spawnPointReference: Transform = GetSpawnPointReference();

     var newObject: Transform = Instantiate(objectTypeToSpawn, spawnPointReference.position, spawnPointReference.rotation) as Transform;

    // do any other stuff with newObject here...

}

 

// function to get a random transform from the list of possible spawn points

function Transform GetSpawnPointReference() 
{

    var  randomIndex: int = Random.Range(0, possibleSpawnPositions.Count);

    return possibleSpawnPositions[randomIndex];

}

There, thanks a lot, i’ll test it out and let you see if i finish it :smile:

I just thought of something that i forget to add. Add a for loop for the number of items or enemies you want. If you wanted it to change based on the level you was on currently, just add a switch for the Level.

var numberOfItems: int; //Or enemies
var newlevel: boolean; // you might have already have this
static var loadedLevelName : String; // Will store the name of the current level

if(newLevel)
{
       switch(Application.loadedLevelName) //Gets the level name and can set whatever vars you want for that level.
       {
             case "Level1": //Of course what you levels are named
                      numberOfItems = 10;
                      break;

             case "Level2":
                      numberOfItems = 7;
                      break;

             case "Level3":
                      numberOfItems = 5; //As the levels get harder or flip it for enemies
                      break;
             default:
                      Debug.Log("Something is wrong here");
                      break;
       }

       for(i=0; i < numberOfItems; i++)
       {
             SpawnNewObject(); 
       }

       newLevel = false;
}

Thanks a lot again, ehm, i was trying to make sense of the first content…and i got only 1 error that i don’t understand at all

It tells me the typical

Yeah, so i noticed…this is the first time i see “Transform” as the beginning of a function

function Transform GetSpawnPointReference()

So i tried encapsulating GetSpawnPointReference() between 2 more parenthesis

function Transform (GetSpawnPointReference())

…it got worse, more errors

Then i tried writing

function Transform (GetSpawnPointReference)

…again, no luck

Then i tried to search help about the main functions in javascript, but i didn’t found any “function transform” function…

So i’m a bit stuck, i want to understand what is this “Transform” for, the more i learn, the better i guess. The rest it’s ok, for now, i’ll add the code from the 2nd reply of rtheprince

Thanks seriously!, i’ll start adding some objects to assign to this script later

Hi again, sorry if im being too disturbing, but i have a couple of things not working

It tells me that ‘i’ is an unknown identifier, so i would create a private varriable for i as a integer?( private var i : int; ), or maybe should replace ‘i’ for the actual name of the gameobject? sorry, i’m a bit confused

Then it says that ‘Count’ is not a member of ‘UnityEngine.Transform[ ]’, should i replace Count with something else?

This is why i’m am so noob, i’m trying to have common sence :stuck_out_tongue:

Sorry, I wrote the Function wrong. It should be

function GetSpawnPointReference ():Transform //So it returns an object of type Transform
{
      //Do something
      return   something;
}

Also about the for loop; here is an example. It works fine, no errors.

            for(i=0; i<6; i++) // i is a random variable, can be any thing. Alot of people use x or y
			{
				shotgunSpread =(Vector3(0,0,i) + shootDirection).normalized;
				Instantiate(shotgun, bulletSpawnPoint.transform.position, Quaternion.LookRotation(shotgunSpread));
			}

Can you post the Script that you are working on?

And replace “.Count” with “.Length”. It will return an int. Sorry for the confusion, I’m writing a lot of different stuff at the moment. Don’t worry about posting the script, I think that should fix all the errors.

Thanks, now i’m researching how to make arrays, and only once i have assigned the transforms, i guess i will be able to test your script

Ok…i’m truly sorry, now that i’ve read carefully your script, you already gave me the arrays in which i can attach the transforms of my gameObjetcs xD, sorry, i was practising a method i found here

I managed to do it, it wasn’t reallly difficult, but i should have noticed your facility before…, anyway, now i’m in the final part of this question, i’m trying to make the objetcs spawn, i’ll let you know the next problems when it comes, thanks!

Ok…the good thing is…I got it!

The Pages spawn in the possible locations as i wanted, but only 1 problem ejem…

I don’t know why but…, sometimes, when i click on one page, well, 2 o more pages seems to spawn in the same place, so the script is perfect for what i wanted, but i need just that final line that would tell unity to don’t repeat the same location, appart from that, the script is almost done, i couldn’t made it without your help, need to fix this and i’ll be ready to go! thanks!

Ok, i’ve been searching for a while and this is what i know:

There is an option for Arrays that allows to remove a certain object from the list, is ‘RemoveAt’, isn’t it? Or even better, maybe use ‘Array.Shift’ to remove the first element in the array.

In the first case, i know i have to…somehow, tell unity in the script WHICH was the last location where a new object was spawned, so i think…i need to return the last used element.

In the case of Array.Shift, i tried writting the code like this:

for(i=0; i < numberOfItems; i++)// i is a random variable, can be any thing. Alot of people use x or y
{
    SpawnNewObject();
             
    possibleSpawnPositions.Shift();
}

But i’m new to this thing about arrays, unity tells me:

‘Shift’ is not a member of ‘Unity.Transform’

So i guess i’m trying to implement Shift in an incorrect way

Any help is appreciated, thanks in advance!

I would do a “array.RemoveAt(place in the random number you generated);”. It has to be an int. I would suggest in the GetSpawnPointReference(), after the randomIndex has been set; remove it by using “possibleSpawnLocations.RemoveAt(randomIndex);”.

The only way this will work is to place it in the SpawnNewObject function after you made the new object. But since randomIndex is a local variable you would have to declare it outside of the GetSpawnPointReference function so it won’t be destroyed after the function. I will try to write it in code in a sec.

// Class variables--------------------------------------------------------------------------------------
var  possibleSpawnPositions: Transform[];
var  objectTypeToSpawn: GameObject;
var randomIndex: int; //This was added to hold the random value made with the GetSpawnPointReference() function
 
// call this function whenever you want to spawn a new object at a random position
function SpawnNewObject() 
{
     var spawnPointReference: Transform = GetSpawnPointReference();

     var newObject: Transform = Instantiate(objectTypeToSpawn, spawnPointReference.position, spawnPointReference.rotation) as Transform;

//This should remove the reference to the position that was just used above. It will be reset the next time GetSpawnReference is called-----------------------------------------------
     possibleSpawnLocations.RemoveAt(randomIndex); 
    // do any other stuff with newObject here...
}


// function to get a random transform from the list of possible spawn points
function GetSpawnPointReference(): Transform 
{
     //This was changed so its not local anymore!---------------------------------------------------------------------------------------------
    randomIndex = Random.Range(0, possibleSpawnPositions.Length);

    return possibleSpawnPositions[randomIndex];
}

ehmm, i tried it, is almost fine but i got the same problem, it tells me that ‘RemoveAt’ is not a member of ‘UnityEngine.Transform[ ]’

(before that, i needed to make a change since apparently there was a misunderstanding, because originally you wrote possibleSpawnPositions but in line 14 it said possibleSpawnLocations, so i just changed to possibleSpawnPositions again, and then, the error above, don’t know exactly how to fix it.

RemoveAt is a function only for lists (or Unity’s array), not arrays. You’ll want to convert possibleSpawnPositions into a list. As for the actual conversion, I hope a JS expert can come in and help. I don’t know how JS lists are defined (It should be different from C#)

Hold a sec. I building a test scene to see if i can get it working.

I got it working! It should work without issue :smile:. I have been testing it out in my own test scene. I’m off to bed, hope this helps.

Oh, I forget explain. You don’t have to drag the Spawn Points in. It will do it at the Start function; then count them. I also remove the other function because it was pointless in this form. It will always work as long as your numberOfItems is equal or smaller than the Spawn Points.

I couldn’t get the Array stuff to work. But there are a million ways to skin a cat!

// Class variables--------------------------------------------------------------------------------------

var  spawnPoints:GameObject[];
var  objectTypeToSpawn: GameObject;
var numberOfItems: int = 5;
var spawnCounter: int;
var itemsSpawned: int;
var randomIndex: int; 

function Start()
{
    itemsSpawned = 0;
	spawnPoints = GameObject.FindGameObjectsWithTag ("SpawnPoint");
    for (var respawn in spawnPoints)
        spawnCounter++;
    
}

function Update()
{
	if(itemsSpawned < numberOfItems)
	{
		SpawnNewObject();
	}
}

function SpawnNewObject() 
{Debug.Log("Checking " + randomIndex);
	var randomIndex: int = Random.Range(0, spawnCounter);
	Debug.Log("Checking " + randomIndex);
    var spawnPointReference: Item = spawnPoints[randomIndex].GetComponent("Item");
    
    if(spawnPointReference.hasItem == false)
    {
    	Instantiate(objectTypeToSpawn, spawnPointReference.transform.position, spawnPointReference.transform.rotation);
    	itemsSpawned ++;
    	Debug.Log("Spawned a item!");
    	spawnPointReference.hasItem = true;
    }
    
}

And I added a script on the spawnPoint called Item. It only contains

var hasItem: boolean = false;

Hi, sorry for taking so long to reply.

I tried the new code, but…i don’t understand how to use it now, you said that don’t need to drag the spawn points in, that it will do it at the start function…how?, i had to copy the code into a new script but i don’t know how to make it work (i also created the ‘Item script’ you put at the end).

I have my spawnpoints all inside an empty object to keep them grouped (the spawn points are lights, so, while i’m testing, i need to see where they are in my dark scene). I just added the main random script and the item script into the main gameObject that has all the spawn points inside as childs…is this right? or what is wrong?

The game runs slowly, and it shows:

NullReferenceException: Object reference not set to an instance of an object
RandomGOSpawn4.SpawnNewObject () (at Assets/Mis Scripts/RandomGOSpawn4.js:38)
RandomGOSpawn4.Update () (at Assets/Mis Scripts/RandomGOSpawn4.js:27)

and

Non matching Profiler.EndSample (BeginSample and EndSample count must match)

Thanks in advance! (sorry for making this thread too long)