Make a coroutine do multiple things

I’m making an adventure game where you have this laser that can disintegrate rocks. Right now I have it so that the player shoots the laser and when the bullet collides with something tagged as destructable, this code is run:

I’m trying to get it so the bullet collides and is immediately destroyed.
The ExpldeFX method instantiates the disintigrateFX (working properly).
It should then wait 2 seconds and delete the collision object.
It should then wait 2 more seconds and delete the disintigrationFX.

Unfortunately only the first things are working. Anything after the first “yield return new WaitForSeconds(2.0f);” never comes up.

Any help would be appreciated, I’m afraid I’m a little lost.

Thanks!

   	void OnCollisionEnter(Collision collision){
    		if (collision.gameObject.tag == "Destroyable"){
    			ExplodeBullet();
    			collidepoint = collision.transform.position;
    			colliderotate = collision.transform.rotation;
    			collideobject = collision.gameObject;
    			Debug.Log (collidepoint);
    			StartCoroutine("ExplodeFX");;
    		}
    	}
    	
    	void ExplodeBullet(){
    			Destroy(gameObject);
    	}
    	
    	IEnumerator ExplodeFX(){
    		for(int i=0;i<5;i++) {
    			GameObject disintigration = (GameObject)Instantiate (disintigrateFX, collidepoint, colliderotate);
    			Debug.Log ("Wait started");
    			yield return new WaitForSeconds(2.0f);
    			Debug.Log ("2 seconds have passed");
    			Destroy(collideobject);
    			yield return new WaitForSeconds(2.0f);
    			Debug.Log ("4 seconds have passed");
    			Destroy(disintigration);
    		}
    	}
    }

The coroutine is linked to the script that created it - if you destroy the object, the coroutine is destroyed too. In this case, the coroutine ExplodeFX is started and executes until the first yield is found, when control returns to the calling code (the bullet script). Since you’ve destroyed the bullet, the coroutine also drops dead.

A possible solution is to create a prefab that’s just an empty object that contains the ExplodeFX script, which executes the old ExplodeFX code in the Start function (converted to a coroutine): instantiate the prefab instead of starting the coroutine, and it will do the job independently of the bullet.

The bullet script could be something like this:

public GameObject explodeFxPrefab; // drag the explodeFX prefab here

void OnCollisionEnter(Collision collision){
    if (collision.gameObject.tag == "Destroyable"){
        // create explode effect controller:
        GameObject explFx = Instantiate(explodeFxPrefab) as GameObject;
        // get the controller script and assign the variables:
        ExplodeFX script = explFx.GetComponent<ExplodeFX>();
        script.collidepoint = collision.transform.position;
        script.colliderotate = collision.transform.rotation;
        script.collideobject = collision.gameObject;
        Destroy(gameObject); // destroy bullet
    }
}

And the explodeFx prefab would have the script ExplodeFX attached to it:

using UnityEngine;
using System.Collections;

public class ExplodeFX : MonoBehaviour {

    public GameObject disintigrateFX; // drag the FX prefab here
    public Vector3 collidepoint; // variables moved to this script
    public Quaternion colliderotate;
    public GameObject collideobject;

    IEnumerator Start(){ // Start now is a coroutine
        for(int i=0;i<5;i++){
            GameObject disintigration = (GameObject)Instantiate (disintigrateFX, collidepoint, colliderotation);
            yield return new WaitForSeconds(2.0f);
            // this will cause problems - see note below
            Destroy(collideobject);
            yield return new WaitForSeconds(2.0f);
            Destroy(disintigration);
        }
        Destroy(gameObject); // destroy the empty after the loop
    }
}

NOTE: This for will only execute once, since you’re destroying the collideobject - this will cause a Null Reference error in the next iteration. You should either move Destroy(collideobject) outside the for loop, or test collideobject before Destroy’ing it (references to a destroyed object become null).