A for loop will instantiate everything at the same time. So all 3 objects unless you iterate once per frame. But then you may aswell have just thrown your death position into a list of a manager script and handled what to do about instantiating when that list has content and it’s elements are being checked.
So I ended up doing this (on a manager script because I destroy the enemy after running the bomb chain ienumerator).
Here’s what I ended up writing:
private void randomizeBombPositionInts()
{
randomX = Random.Range(-1.5f, 1.5f);
randomY = Random.Range(-1.5f, 1.5f);
}
public IEnumerator BombChain(Vector3 enemyPosition)
{
for (int i = 0; i < magicBomb; i++)
{
Debug.Log("Bomb spawned");
randomizeBombPositionInts();
Instantiate(magicBombItem, new Vector2(enemyPosition.x + randomX, enemyPosition.y + randomY), transform.rotation);
yield return new WaitForSeconds(.1f);
}
}
The issue I’m encountering is that it’s only running the for loop once. I have debugged to confirm this, and I can also confirm that the “magicBomb” int is 3 when running, so it should be dropping 3 bombs right?
What object is actually starting this co-routine? Depending on how you’ve done it, the object you’re destroying could still be the monobehaviour this co-routine is attached to; thus it will only perform one execution before being destroyed and killing the co-routine.
Sure yeah, so the script above is on a manager called ItemTracker and the coroutine is being called from an enemy before it dies. That’s here:
if (ItemTracker.instance.magicBomb > 0)
{
StartCoroutine(ItemTracker.instance.BombChain(transform.position));
}
I understand your concern about the enemy being destroyed, but as far as I’m aware all I’m doing is starting the coroutine and setting the position of the bomb spawn from the enemy before destroying it. Everything else should be playing out on the ItemTracker without issue.
No you’re doing exactly what I said would cause the issue. You’re starting the co-routine from the object being destroyed, tying the lifetime of the co-routine to it. Thus, when the enemy is destroyed, the co-routine is killed.
You can avoid all this ownership and lifetime noise by using a simple “do something later” script.
I use my CallAfterDelay class for delayed action.
See usage notes at bottom below gist code.
In your case you would issue CallAfterDelay instances for each of the bombs with ever-increasing delays, then you can just go away fearlessly and as each CallAfterDelay matures, the spawn will happen, something like:
using UnityEngine;
public class MakeLineOfBombs : MonoBehaviour
{
void Start()
{
for (int i = 0; i < 10; i++)
{
Vector3 spawnPosition = Vector3.right * (i - 5);
float time = i * 0.25f;
// @kurtdekker... get this from:
// https://gist.github.com/kurtdekker/0da9a9721c15bd3af1d2ced0a367e24e
CallAfterDelay.Create( time, () => {
var bomb = GameObject.CreatePrimitive( PrimitiveType.Sphere);
bomb.transform.position = spawnPosition;
});
}
// we can happily go away now
Destroy(gameObject);
}
}
Thank you! I ended up doing a variation of this that worked.
I created a “BombChainCreator” script & prefab, and just had that spawn at each enemy’s death, then from there instantiate the bombs from that script in the position of that new frefab object. It’s working great now!