- Home /
Problem with spawning at a random point
Hey all,
I have a problem with some random spawning of game objects. I wish to spawn an exit in a randomly created dungeon, but I think my code has an infinite loop somewhere, as Unity freezes when the code is ran. At the moment, the "exit" is just an empty Game Object with a point light attached (so I can easily see it).
var ExitPiece : GameObject //The GO used for the exit. Its just a pointlight at the moment
var DungeonSizeX : int = 3; //The length the dungeon will be, measured in spawned pieces
var DungeonSizeY : int = 3; //The width the dungeon will be, measured in spawned pieces
var PartSize : int = 4 //The dimensions (length and width) of the pieces that are used, measured in Unity units
function GenerateExit () {
Debug.Log("Creating exit");
var SpawnedExit : boolean = false;
while(!SpawnedExit){
P1 = Random.Range(0, DungeonSizeX*PartSize);
P2 = Random.Range(0, DungeonSizeY*PartSize);
ExitPoint = Vector3(P1, 1.25, P2);
hit = RaycastHit;
//Casts a ray at the ExitPoint. If the ray hits something, the exit isnt created
if(!Physics.OverlapSphere(ExitPoint, 1f)){
Instantiate(ExitPiece, ExitPoint, Quaternion.identity);
SpawnedExit = true;
Debug.Log("Exit created at point: " +(ExitPoint.ToString()));
}
else{
Debug.LogError("Exit creation failed");
}
}
}
The code to create the dungeons is here, and this function is called after after GenerateWall.
The pieces I'm using are all 2.5units tall, and 4 units wide, so the overlapSphere should be able to find a place to spawn the exit. I've tried reducing the radius, but Unity still freezes.
Any help?
The problem here is that there is nothing in your code which guarantees that the loop will finish, even if it were working properly. It is quite possible for Random.Range to constantly pick only values which fail!
Another thing- how big are your segments? It's possible that the 1-radius overlapSphere is always overlapping the walls, and so always returns true. Try with a radius of 0.01 or something, to see if that works better.
I have tried reducing the radius, but that still froze unity. Are there any other ways I could do this, that would guarantee it works?
I use this same technique to spawn boxes in the dungeon, and that works every time, so I really dont know whats happening here.
Ah, so it works elsewhere? The exact same code? It's possible that the infinite loop is occuring somewhere in ExitPiece's initialization code. What happens in that object's Start?
Just looked over your generation code- $$anonymous$$aybe you could make the 'exit' be a special kind of dungeon tile? Then have it generate in the part where the dungeon spawns, but with some checks to make sure it always generates exactly once per dungeon.
This is just tacked onto the end of here: http://answers.unity3d.com/questions/179450/random-dungeon-generation.html , and the code works fine if I dont call this function.
I use the same method for spawning the boxes, but I dont use a boolean, I use a counter. (I cant check, but its something along the lines of while(i != 100) and I add increase i by one, only if a box spawns).
Oh, and I have tried this with a counter as well
Answer by Owen-Reynolds · Dec 04, 2011 at 03:42 PM
The usual way to run a "try until I get it" loop is to use an extra var for number of tries. If you try some insane number of times, it must not be possible.
Also, say you have 10 tiles, 4 wide. Instead of rolling 0 to 40, you really want to roll tile 0-9 and then try the location of the center of that tile. To get the center of a tile, add width for all previous tiles, then 1/2width to get to the center of that one:
int tries=0;
bool done=false;
while(!done && tries<1000) {
tries++;
P1 = Random.Range(0, DungeonSizeX); // roll the square# 0-9
// convert square# into position on map, center of square:
P1 = P1 * PartSize + PartSize/2.0;
...
}
if(!done) Debug.Log("can't find exit. Make new dungeon.");
But, as mentioned above, a better solution is to look in the array making it, instead of the 3D map created from the array.
This is more what I'm after, thanks! I'll try both this method and syclamoth's solution later today, and see which one "works better".