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): using System.Collections; using System.Collections.Generic; using UnityEngine; public class DamageIcon : MonoBehaviour { public Sprite[] damageSprites; public float lifetime; public GameObject effect; public void Start() { Invoke("Destruction", lifetime); StartCoroutine("waitThreeSeconds"); } IEnumerator waitThreeSeconds() { yield return new WaitForSeconds(3); } public void Setup (int damage) { GetComponent<SpriteRenderer>().sprite = damageSprites[damage - 1]; } void Destruction() { Instantiate(effect, transform.position, Quaternion.identity); Destroy(gameObject); } }
Code (CSharp): public void Start() { StartCoroutine("waitThreeSeconds"); } IEnumerator waitThreeSeconds() { yield return new WaitForSeconds(3); Destruction(); } public void Setup (int damage) { GetComponent<SpriteRenderer>().sprite = damageSprites[damage - 1]; } void Destruction() { Instantiate(effect, transform.position, Quaternion.identity); Destroy(gameObject); } Something more like that maybe?
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): void Attack(Unit enemy) { animator.SetTrigger("Attack"); camAnim.SetTrigger("Shake"); hasAttacked = true; int enemyDamage = attackDamage - enemy.armor; int myDamage = enemy.defenseDamage - armor; if (enemyDamage >= 1) { StartCoroutine(waitThreeSeconds()); IEnumerator waitThreeSeconds() { yield return new WaitForSeconds(3); } DamageIcon instance = Instantiate(damageIcon, enemy.transform.position, Quaternion.identity); instance.Setup(enemyDamage); enemy.health -= enemyDamage; enemy.UpdateKingHealth(); }
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]
hi havyx, where would I have to put the startcoroutine? I think I am still not 100% clear with them... Code (CSharp): void Attack(Unit enemy) { animator.SetTrigger("Attack"); camAnim.SetTrigger("Shake"); hasAttacked = true; int enemyDamage = attackDamage - enemy.armor; int myDamage = enemy.defenseDamage - armor; if (enemyDamage >= 1) { StartCoroutine(waitThreeSeconds()); [B]DOES NOT WORK, SADFACE[/B] IEnumerator waitThreeSeconds() { yield return new WaitForSeconds(3); } DamageIcon instance = Instantiate(damageIcon, enemy.transform.position, Quaternion.identity); instance.Setup(enemyDamage); enemy.health -= enemyDamage; enemy.UpdateKingHealth(); }
Consider a coroutine like a normal method. You are attempting to declare a method within another method. Code (CSharp): void SomeMethod() { IEnumerator YouAreTryingToDeclareACoroutineWithinAnotherMethod() { } } You need to move the IEnumerator from inside the Attack method into it's own method. Code (CSharp): void SomeMethod() { IEnumerator ThisWillNotWork() { } } Code (CSharp): void SomeMethod() { } IEnumerator ThisWillWork() { } Code (CSharp): void Attack(Unit enemy) { animator.SetTrigger("Attack"); camAnim.SetTrigger("Shake"); hasAttacked = true; int enemyDamage = attackDamage - enemy.armor; int myDamage = enemy.defenseDamage - armor; if (enemyDamage >= 1) { StartCoroutine(waitThreeSeconds()); } } IEnumerator waitThreeSeconds() { yield return new WaitForSeconds(3); DamageIcon instance = Instantiate(damageIcon, enemy.transform.position, Quaternion.identity); instance.Setup(enemyDamage); enemy.health -= enemyDamage; enemy.UpdateKingHealth(); }
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.
In the general case, if you just want something cheap and cheerful to take place three seconds from now, you can use a construct like this one: https://gist.github.com/kurtdekker/0da9a9721c15bd3af1d2ced0a367e24e See the notes at the bottom of the page for more info and usage examples.
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.
oh boy, this is actually more complicated than I thought 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!