Search Unity

Wait For Seconds

Discussion in 'Scripting' started by TomsTales, Jan 23, 2021.

  1. TomsTales

    TomsTales

    Joined:
    Nov 3, 2020
    Posts:
    91
    Hi Guys, can someone maybe look at my code and tell me what I am doing wrong?

    Instantiate should wait 3 seconds...

    Cheers!

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class DamageIcon : MonoBehaviour
    6. {
    7.     public Sprite[] damageSprites;
    8.     public float lifetime;
    9.  
    10.     public GameObject effect;
    11.  
    12.     public void Start()
    13.     {
    14.         Invoke("Destruction", lifetime);
    15.         StartCoroutine("waitThreeSeconds");
    16.     }
    17.     IEnumerator waitThreeSeconds()
    18.     {
    19.         yield return new WaitForSeconds(3);
    20.     }
    21.  
    22.     public void Setup (int damage)
    23.     {
    24.         GetComponent<SpriteRenderer>().sprite = damageSprites[damage - 1];
    25.     }
    26.     void Destruction()
    27.     {
    28.         Instantiate(effect, transform.position, Quaternion.identity);
    29.         Destroy(gameObject);
    30.     }
    31. }
    32.  
     
  2. pantang

    pantang

    Joined:
    Sep 1, 2016
    Posts:
    219

    1. Code (CSharp):
      1.     public void Start()
      2.     {
      3.         StartCoroutine("waitThreeSeconds");
      4.     }
      5.     IEnumerator waitThreeSeconds()
      6.     {
      7.         yield return new WaitForSeconds(3);
      8.         Destruction();
      9.     }
      10.  
      11.     public void Setup (int damage)
      12.     {
      13.         GetComponent<SpriteRenderer>().sprite = damageSprites[damage - 1];
      14.     }
      15.     void Destruction()
      16.     {
      17.         Instantiate(effect, transform.position, Quaternion.identity);
      18.         Destroy(gameObject);
      19.     }
      Something more like that maybe?
     
  3. TomsTales

    TomsTales

    Joined:
    Nov 3, 2020
    Posts:
    91
    thank you, sadly that does not make it wait :/
     
  4. Havyx

    Havyx

    Joined:
    Oct 20, 2020
    Posts:
    140
    Code (CSharp):
    1.  
    2.     public void Start()
    3.     {
    4.         StartCoroutine(waitThreeSeconds());
    5.     }
    6.  
    7.  
     
  5. TomsTales

    TomsTales

    Joined:
    Nov 3, 2020
    Posts:
    91
    Thank you lol, didnt see the missing (). This does work indeed. However at another position, it doesnt...maybe you can explain me why? damageIcon should wait

    Code (CSharp):
    1.     void Attack(Unit enemy)
    2.     {
    3.         animator.SetTrigger("Attack");
    4.         camAnim.SetTrigger("Shake");
    5.         hasAttacked = true;
    6.  
    7.        
    8.         int enemyDamage = attackDamage - enemy.armor;
    9.         int myDamage = enemy.defenseDamage - armor;
    10.  
    11.  
    12.         if (enemyDamage >= 1)
    13.         {
    14.             StartCoroutine(waitThreeSeconds());
    15.             IEnumerator waitThreeSeconds()
    16.             {
    17.                 yield return new WaitForSeconds(3);
    18.             }
    19.  
    20.             DamageIcon instance = Instantiate(damageIcon, enemy.transform.position, Quaternion.identity);
    21.             instance.Setup(enemyDamage);
    22.             enemy.health -= enemyDamage;
    23.             enemy.UpdateKingHealth();
    24.         }
     
  6. Havyx

    Havyx

    Joined:
    Oct 20, 2020
    Posts:
    140

    The IEnumerator is inside of the Attack method. This should exist on it's own (like a normal method).

    Also, this is unlikely to work either. Coroutines are asynchronous meaning the rest of that code will execute straight away.

    Might be better to put the code you want to execute after the wait time.

    IEnumerator waitThreeSeconds()
    {
    yield return new WaitForSeconds(3);

    DamageIcon instance = Instantiate(damageIcon, enemy.transform.position, Quaternion.identity);
    instance.Setup(enemyDamage);
    enemy.health -= enemyDamage;
    enemy.UpdateKingHealth();
    }
    [/code]
     
  7. TomsTales

    TomsTales

    Joined:
    Nov 3, 2020
    Posts:
    91
    hi havyx, where would I have to put the startcoroutine? I think I am still not 100% clear with them...

    Code (CSharp):
    1. void Attack(Unit enemy)
    2.     {
    3.         animator.SetTrigger("Attack");
    4.         camAnim.SetTrigger("Shake");
    5.         hasAttacked = true;
    6.  
    7.        
    8.         int enemyDamage = attackDamage - enemy.armor;
    9.         int myDamage = enemy.defenseDamage - armor;
    10.  
    11.  
    12.         if (enemyDamage >= 1)
    13.         {
    14.             StartCoroutine(waitThreeSeconds()); [B]DOES NOT WORK, SADFACE[/B]
    15.             IEnumerator waitThreeSeconds()
    16.             {
    17.                 yield return new WaitForSeconds(3);
    18.             }
    19.             DamageIcon instance = Instantiate(damageIcon, enemy.transform.position, Quaternion.identity);
    20.             instance.Setup(enemyDamage);
    21.             enemy.health -= enemyDamage;
    22.             enemy.UpdateKingHealth();
    23.         }
    24.  
     
  8. Havyx

    Havyx

    Joined:
    Oct 20, 2020
    Posts:
    140
    Consider a coroutine like a normal method. You are attempting to declare a method within another method.

    Code (CSharp):
    1.  
    2. void SomeMethod()
    3. {
    4.     IEnumerator YouAreTryingToDeclareACoroutineWithinAnotherMethod()
    5.     {
    6.     }
    7. }
    8.  
    You need to move the IEnumerator from inside the Attack method into it's own method.

    Code (CSharp):
    1.  
    2. void SomeMethod()
    3. {
    4.     IEnumerator ThisWillNotWork()
    5.     {
    6.     }
    7. }
    8.  
    Code (CSharp):
    1.  
    2. void SomeMethod()
    3. {
    4.    
    5. }
    6.  
    7. IEnumerator ThisWillWork()
    8. {
    9.  
    10. }
    11.  
    Code (CSharp):
    1.  
    2. void Attack(Unit enemy)
    3. {
    4.     animator.SetTrigger("Attack");
    5.     camAnim.SetTrigger("Shake");
    6.     hasAttacked = true;
    7.  
    8.     int enemyDamage = attackDamage - enemy.armor;
    9.     int myDamage = enemy.defenseDamage - armor;
    10.  
    11.  
    12.     if (enemyDamage >= 1)
    13.     {
    14.         StartCoroutine(waitThreeSeconds());
    15.     }
    16. }
    17.  
    18. IEnumerator waitThreeSeconds()
    19. {
    20.     yield return new WaitForSeconds(3);
    21.  
    22.      DamageIcon instance = Instantiate(damageIcon, enemy.transform.position, Quaternion.identity);
    23.      instance.Setup(enemyDamage);
    24.      enemy.health -= enemyDamage;
    25.      enemy.UpdateKingHealth();
    26. }
    27.  
     
  9. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    3,999
    While I also strongly recommend to move the coroutine out of the Attack method, it's not necessary with the newest C# version since we now have local method support. However local methods can be very confusing and just increase the over all indention depth and method length.

    Though the most important thing is that the coroutine of the OP is completely pointless. Starting a coroutine means it's running seperately from the starting code. So the code after the StartCoroutine call will continue immediately. You can only wait inside a coroutine. So if you want code to execute once the WaitForSecond is over, that code has to be inside the coroutine and after the yield instruction.
     
    Havyx likes this.
  10. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,735
  11. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    3,999
    This is a bit of an overkill. A seperate gameobject has quite a memory overhead and also requires registration in the scene. You could use something like my CoroutineHelper which is a singleton gameobject that will house all the coroutines and supports different execution modes for delegates.
     
  12. TomsTales

    TomsTales

    Joined:
    Nov 3, 2020
    Posts:
    91
    oh boy, this is actually more complicated than I thought :D

    I will try to get my head around it, but is there no easier way to just stop the script for some seconds if damage is done...hm I try what you suggested!