So Im trying to add power ups to my game, and the first one should spawn after 3 seconds the game started.
For that I decided to create a coroutine that is activated in the case of no gameobject with the “PowerUp” tag was found, and when the gameobject with the “PowerUp” is detected, the coroutine should stop.
The first part is going well, the script detects that theres no “PowerUp” tagged gameobject and then the power up gets instantiated after the coroutine given time.
But after starting, the coroutine never stops and keeps instantiating the powerup prefab. How can I fix this? Thanks in advance
public class PickupPower : MonoBehaviour {
public GameObject[] powerUpArray;
GameObject powerUp;
Vector2 powerPos;
int powerCount;
void Start() {
powerPos = new Vector2(0, 5);
}
// Update is called once per frame
void Update () {
powerUp = GameObject.FindGameObjectWithTag("PowerUp");
if (powerUp ==null) {
StartCoroutine(SpawnPower());
}
if (powerUp != null) {
print("found PowerUp");
StopCoroutine(SpawnPower());
}
}
IEnumerator SpawnPower() {
yield return new WaitForSeconds(3);
Instantiate(powerUpArray[Random.Range(0, powerUpArray.Length)], powerPos, transform.rotation);
}
}
PS: the print (“found PowerUp”) is working just fine, but idk why it doesnt stop the coroutine, guess idk how to use them :s
Even the question is already answered, there are too many issues in the original code. Here’s a powerup spawner that should fit most peoples mind:
public class PowerUpSpawner : MonoBehaviour
{
public GameObject[] powerUpArray;
public float initialDelay = 3;
public bool autoRespawn = true;
public float minWaitTime = 30;
pubilc float maxWaitTime = 30;
GameObject powerUp;
void Start()
{
if (transform.childCount > 0)
powerUp = transform.GetChild(0);
StartCoroutine(Spawn());
}
IEnumerator Spawn ()
{
yield return new WaitForSeconds(initialDelay);
while(true)
{
while(powerUp != null)
yield return null;
var prefab = powerUpArray[Random.Range(0, powerUpArray.Length)];
powerUp = Instantiate(prefab, transform.position, transform.rotation);
powerUp.transform.parent = transform;
yield return new WaitForSeconds(Random.Range(minWaitTime, maxWaitTime));
while (autoRespawn == false)
yield return null;
}
}
}
Some important notes:
This script should be attached to an empty gameobject in the scene.
It’s location and orientation is used to specify the spawn position and orientation.
There shouldn’t be any child objects other than the instantiated powerup prefab.
When a prefab is “picked up” it need to be Destroyed. Pooling the object won’t work here since we are waiting for the destruction of the powerup. If you want to implement pooling, of course you have to exchange the instantiate with some activate code of the right instance and don’t do a null check in the inner while loop, but check if the powerup is active. When the powerup is picked up it would be deactivated instead of being destroyed.
The initialDelay specifies when the first powerup should spawn. The min and max WaitTime specifies when the powerup should respawn after it was picked up. Setting both to the same number respawns at a fix delay.
Setting “autoRespawn” to false will pause the respawning mechanism until it is set back to true
The spawner will make the spawned powerup a child of itself. This way when you have multiple powerup spawners each spawner is handling it’s own spawned powerup.
Note that technically this could be used to spawn anything that should respawn once the originally spawned object has been destroyed. So it could even be used as enemy spawner^^. Though it always spawns only a single object which it tracks until destroyed. However you could use several spawners at the same time.