- Home /
How to spawn objects using an array of spawn points w/o intersecting
I am trying to spawn pick-up objects at random places in my game area using an array of spawn points, but I cannot seem to figure out the correct way to check to see an object has already spawned there. I am using an InvokeRepeating() function to instantiate these objects over and over until the player wins or loses. But I don't want another object to be instantiated where another one already is. I have tried using OnTriggerEnter(), but since they are both non-kinematic triggers, it does not work. I have tried using CheckSphere(), but since they are instantiated on floating platforms, none end up being instantiated because it senses that the platforms (and probably the empty spawn point objects) intersect. I am going crazy trying to wrack my brain to figure this out. Please help!
-Thanks!
Answer by tcjulian · Dec 11, 2017 at 09:10 AM
If I understand you correctly, you have a finite set of points where objects could spawn, and you want to make sure that objects may only spawn at one of these points if nothing has spawned there already.
If the spawned objects won't move, you can keep track of which spawn points have already been used. If the objects can be destroyed, you just need to make sure that when that happens, you mark the corresponding spawn point as unused again.
[SerializedField] Vector3[] _possibleSpawnPoints;
bool[] _usedSpawnPoints; // Corresponds to _possibleSpawnPoints. Eg if _usedSpawnPoints[0] == true, _possibleSpawnPoints[0] is no longer viable
void Awake () {
_usedSpawnPoints = new bool[_possibleSpawnPoints.Length];
}
void SpawnAtRandomSpawnPoint () {
int spawnIndex = Random.Range(0, _possibleSpawnPoints.Length);
int checkedPoints = 0;
while (_usedSpawnPoints[spawnIndex]) { // If a spawn point is occupied
spawnIndex = (spawnIndex + 1) % _possibleSpawnPoints.Length; // Pick the next available spawn point
checkedPoints++;
if (checkedPoints >= _possibleSpawnPoints.Length) {
return; // No spawn points available
}
}
SpawnAtIndex(spawnIndex);
}
void SpawnAtPoint (int index) {
Vector3 spawnLocation = _possibleSpawnPoints[index];
// TODO: Spawn object at spawnLocation
_usedSpawnPoints[index] = true; // Mark spawn point as having been used
}
If you can use a List<T>
instead of an array, you could remove points from it as they get used.
If the spawned objects may move, you might want to do something like you were considering, with overlap tests, but make sure the tests only check for the spawned objects, so that your tests don't include platforms. The easiest way would be with something like https://docs.unity3d.com/ScriptReference/Physics.OverlapSphereNonAlloc.html, using a LayerMask
to exclude the platforms. If the platforms need to be on the same layer, you could still use Physics.OverlapSphereNonAlloc
but iterate through the results
to exclude the platforms, by using https://docs.unity3d.com/ScriptReference/Component.CompareTag.html or testing for the presence of a component with https://docs.unity3d.com/ScriptReference/Component.GetComponent.html using something like results[i] .GetComponent<Platform>() != null
as a test.
Your answer
Follow this Question
Related Questions
How to prevent multiple spawns from a single spawn point? 1 Answer
Game object spawning, spawn conditions and spawning location problems. 1 Answer
[Help] How Do I Randomly Spawn Game Objects On Specific Coordinates? 3 Answers
Spawning help 1 Answer
How do I spawn more the one spawnpoints ramdomly in my scene / Spawning problems 0 Answers