Randomly placing items script not working - sometimes items spawn in walls, sometimes items spawn in weird locations
- by Timothy Williams
I'm trying to figure out a way to randomly spawn items throughout my level, however I need to make sure they won't spawn inside another object (walls, etc.)
Here's the code I'm currently using, it's based on the Physics.CheckSphere(); function.
This runs OnLevelWasLoaded();
It spawns the items perfectly fine, but sometimes items spawn partway in walls. And sometimes items will spawn outside of the SpawnBox range (no clue why it does that.)
//This is what randomly generates all the items.
void SpawnItems () {
if (Application.loadedLevelName == "Menu" || Application.loadedLevelName == "End Demo")
return;
//The bottom corner of the box we want to spawn items in.
Vector3 spawnBoxBot = Vector3.zero;
//Top corner.
Vector3 spawnBoxTop = Vector3.zero;
//If we're in the dungeon, set the box to the dungeon box and tell the items we want to spawn.
if (Application.loadedLevelName == "dungeonScene") {
spawnBoxBot = new Vector3 (8.857f, 0, 9.06f);
spawnBoxTop = new Vector3 (-27.98f, 2.4f, -15);
itemSpawn = dungeonSpawn;
}
//Spawn all the items.
for (i = 0; i != itemSpawn.Length; i ++) {
spawnedItem = null;
//Zeroes out our random location
Vector3 randomLocation = Vector3.zero;
//Gets the meshfilter of the item we'll be spawning
MeshFilter mf = itemSpawn[i].GetComponent<MeshFilter>();
//Gets it's bounds (see how big it is)
Bounds bounds = mf.sharedMesh.bounds;
//Get it's radius
float maxRadius = new Vector3 (bounds.extents.x + 10f, bounds.extents.y + 10f, bounds.extents.z + 10f).magnitude * 5f;
//Set which layer is the no walls layer
var NoWallsLayer = 1 << LayerMask.NameToLayer("NoWallsLayer");
//Use that layer as your layermask.
LayerMask layerMask = ~(1 << NoWallsLayer);
//If we're in the dungeon, certain items need to spawn on certain halves.
if (Application.loadedLevelName == "dungeonScene") {
if (itemSpawn[i].name == "key2" || itemSpawn[i].name == "teddyBearLW" || itemSpawn[i].name == "teddyBearLW_Admiration" || itemSpawn[i].name == "radio")
randomLocation = new Vector3(Random.Range(spawnBoxBot.x, -26.96f), Random.Range(spawnBoxBot.y, spawnBoxTop.y), Random.Range(spawnBoxBot.z, -2.141f));
else
randomLocation = new Vector3(Random.Range(spawnBoxBot.x, spawnBoxTop.x), Random.Range(spawnBoxBot.y, spawnBoxTop.y), Random.Range(-2.374f, spawnBoxTop.z));
}
//Otherwise just spawn them in the box.
else
randomLocation = new Vector3(Random.Range(spawnBoxBot.x, spawnBoxTop.x), Random.Range(spawnBoxBot.y, spawnBoxTop.y), Random.Range(spawnBoxBot.z, spawnBoxTop.z));
//This is what actually spawns the item. It checks to see if the spot where we want to instantiate it is clear, and if so it instatiates it. Otherwise we have to repeat the whole process again.
if (Physics.CheckSphere(randomLocation, maxRadius, layerMask))
spawnedItem = Instantiate(itemSpawn[i], randomLocation, Random.rotation);
else
i --;
//If we spawned something, set it's name to what it's supposed to be. Removes the (clone) addon.
if (spawnedItem != null)
spawnedItem.name = itemSpawn[i].name;
}
}
What I'm asking for is if you know what's going wrong with this code that it would spawn stuff in walls. Or, if you could provide me with links/code/ideas of a better way to check if an item will spawn in a wall (some other function than Physics.CheckSphere).
I've been working on this for a long time, and nothing I try seems to work. Any help is appreciated.