Search Unity

How to execute destroy after coroutine?

Discussion in 'Scripting' started by justadeveloper, Nov 23, 2015.

  1. justadeveloper

    justadeveloper

    Joined:
    Jan 12, 2014
    Posts:
    33
    So, I want to execute my coroutine first then destroy the object, but it works so weird,the destroy always executed first instead of my coroutine

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class Touch : MonoBehaviour
    5. {
    6.     private SpriteRenderer spriteGameObject;
    7.    
    8.     //Update is called once per frame
    9.     void Update ()
    10.     {
    11.             if (Application.platform == RuntimePlatform.WindowsEditor) // Else if Desktop
    12.             {
    13.                     rayCol();
    14.             }
    15.     }
    16.  
    17.     private void rayCol()
    18.     {
    19.         Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
    20.         RaycastHit hit = new RaycastHit();
    21.  
    22.         if(Input.GetMouseButtonDown(0))
    23.         {
    24.             if(Physics.Raycast(ray, out hit))
    25.             {
    26.                 spriteGameObject = hit.transform.GetComponent<SpriteRenderer> ();
    27.                 StartCoroutine(Fade(spriteGameObject));
    28.                 Destroy(spriteGameObject.gameObject);
    29.             }
    30.         }
    31.     }
    32.  
    33.     IEnumerator Fade(SpriteRenderer spriteName)
    34.     {
    35.         for (float f = 1f; f > -0.01f; f -= 0.1f)
    36.         {
    37.             Color c = spriteName.material.color;
    38.             c.a = f;
    39.             spriteName.material.color = c;
    40.             yield return null;
    41.         }
    42.     }
    43. }
    44.  
    45.  
    46.  
     
  2. LeftyRighty

    LeftyRighty

    Joined:
    Nov 2, 2012
    Posts:
    5,148
    you're not using the coroutine correctly.

    when you call "start coroutine" the coroutine's code is run, it gets to the null return, the code execution "skips" the rest of the coroutine's code and then continues to the next line of the function i.e. destroy.

    if you want the destroy to happen after the coroutine add it after the for in the coroutine.
     
    Kiwasi likes this.
  3. justadeveloper

    justadeveloper

    Joined:
    Jan 12, 2014
    Posts:
    33
    I dont really understand,why the return null skips the rest of code when i put destroy outside of coroutine?
     
  4. Kamilche_

    Kamilche_

    Joined:
    Jan 11, 2015
    Posts:
    75
    Put the destroy inside the Fade routine, otherwise the gameObject gets destroyed before the fade is done. Put it outside of the loop, but inside the Fade routine.

    If that is unappealing because Fade is used elsewhere in the program, make a separate routine called FadeThenDestroy and do it there, calling out to subroutines as necessary.
     
  5. justadeveloper

    justadeveloper

    Joined:
    Jan 12, 2014
    Posts:
    33
    yeah i tried it and its working....but i need an explanation about why the return null skips the rest of code when i put destroy after start(courotine)
     
  6. Kamilche_

    Kamilche_

    Joined:
    Jan 11, 2015
    Posts:
    75
    I'm fairly new to Unity myself, so if this explanation is wrong, feel free to correct me. But it doesn't skip the rest of the code, it merely delays execution of it until after the next frame starts. Now, the object is destroyed at the ending of the frame... but when the loop resumes execution, bam the gameObject is gone and you'll get errors.

    So - it didn't cancel execution of the code, it merely delayed it and let other processing through. That other processing ate your object, and now your dog has no meal, and is left growling.
     
  7. Munchy2007

    Munchy2007

    Joined:
    Jun 16, 2013
    Posts:
    1,735
    If you want to keep the Destroy() call out of the Coroutine you could implement a callback and handle it with inline code, maybe something like this:-

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. public class Touch : MonoBehaviour
    4. {
    5.     private SpriteRenderer spriteGameObject;
    6.    
    7.     //Update is called once per frame
    8.     void Update ()
    9.     {
    10.         if (Application.platform == RuntimePlatform.WindowsEditor) // Else if Desktop
    11.         {
    12.             rayCol();
    13.         }
    14.     }
    15.     private void rayCol()
    16.     {
    17.         Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
    18.         RaycastHit hit = new RaycastHit();
    19.         if(Input.GetMouseButtonDown(0))
    20.         {
    21.             if(Physics.Raycast(ray, out hit))
    22.             {
    23.                 spriteGameObject = hit.transform.GetComponent<SpriteRenderer> ();
    24.                 StartCoroutine(Fade(spriteGameObject, delegate() {
    25.                     Destroy(spriteGameObject.gameObject);
    26.                 }));
    27.             }
    28.         }
    29.     }
    30.  
    31.     IEnumerator Fade(SpriteRenderer spriteName, System.Action callback)
    32.     {
    33.         for (float f = 1f; f > -0.01f; f -= 0.1f)
    34.         {
    35.             Color c = spriteName.material.color;
    36.             c.a = f;
    37.             spriteName.material.color = c;
    38.             yield return null;
    39.         }
    40.         callback.Invoke();
    41.     }
    42. }