Problems WaitForSeconds
Hey i'm quite new to unity and everything, can someone please help me and tell me why after the WaitForSeconds spawner, enemy1 and enemy2 do not set to true and Debug.Log("Timer Finished") is not called?
Thanks!
public GameObject effect;
public GameObject powerUpEffect1;
public GameObject explosionSound;
public GameObject spawner;
public GameObject Enemy1;
public GameObject Enemy2;
private void OnTriggerEnter2D(Collider2D other)
{
if (other.CompareTag("Player"))
{
StartCoroutine(powerUp(other));
}
}
private IEnumerator powerUp(Collider2D player)
{
Debug.Log("Timer started");
Instantiate(effect, transform.position, Quaternion.identity);
Instantiate(explosionSound, transform.position, Quaternion.identity);
spawner.SetActive(false);
Enemy1.SetActive(false);
Enemy2.SetActive(false);
powerUpEffect1.SetActive(true);
GetComponent<SpriteRenderer>().enabled = false;
GetComponent<CircleCollider2D>().enabled = false;
yield return new WaitForSeconds(10.0f);
Debug.Log("Timer Finished");
spawner.SetActive(true);
Enemy1.SetActive(true);
Enemy2.SetActive(true);
Destroy(gameObject);
}
Answer by jaca6767 · Jan 28 at 09:00 PM
I believe that with the way that yield works, a function containing a WaitForSeconds command cannot be marked as private. Removing this field should allow it to work properly.
First of all thanks @jaca6767 for answering me, I tried to write the code as you advised me but nothing changed. I noticed that if I enter a value higher than 3 seconds I get the problem I'm having, while if I enter a value equal to or less than 3 everything works perfectly. I don't really understand where the problem is :(
public class PowerUp : MonoBehaviour {
public GameObject effect;
public GameObject powerUpEffect1;
public GameObject explosionSound;
public GameObject spawner;
public GameObject Enemy1;
public GameObject Enemy2;
void OnTriggerEnter2D(Collider2D other)
{
if (other.CompareTag("Player"))
{
StartCoroutine(powerUp(other));
}
}
IEnumerator powerUp(Collider2D player)
{
Debug.Log("Timer started");
Instantiate(effect, transform.position, Quaternion.identity);
Instantiate(explosionSound, transform.position, Quaternion.identity);
spawner.SetActive(false);
Enemy1.SetActive(false);
Enemy2.SetActive(false);
powerUpEffect1.SetActive(true);
GetComponent<SpriteRenderer>().enabled = false;
GetComponent<CircleCollider2D>().enabled = false;
yield return new WaitForSeconds(10);
Debug.Log("Timer Finished");
spawner.SetActive(true);
Enemy1.SetActive(true);
Enemy2.SetActive(true);
Destroy(gameObject);
}
I mean its a bad idea, but you could just write the command 4 times with a value of 3,3,3, and 1. A bodge but if that works, it'd be a temporary fix.
Answer by jaca6767 · Jan 29 at 11:14 PM
Ok, I think I've found a replacement. It may be best to split it into two functions. Have the first part run activating the power up before invoking another function to disable it after a certain duration. You can find the documentation for invoke here.
A sample piece of code like this would be:
void OnTriggerEnter(whatever)
{
//Call first stuff here
Invoke(done, 10);
}
void done()
{
//deactivation here.
}
i really don't know where's the problem, it doesn't let me wait more then 3 seconds. i also tried to use more invoke but nothing has changed
like this:
void picked1()
{
Invoke("picked2", 3f);
}
void picked2()
{
Invoke("picked3", 3f);
}
void picked3()
{
Invoke("picked", 1f);
}
I really don't know. If u also don't know don't worry man, thanks for your help anyways.
Answer by privatecontractor · Jan 30 at 07:39 PM
Hi @SakiHub,
really weird problem, maybe you could try some detour? So instead of:
yield return new WaitForSeconds(10.0f);
Let's use:
float m_remaingDelayTime = 10.0f;
while (m_remainingDelayTime > 0)
{
m_remainingDelayTime -= Time.deltaTime;
yield return null;
}
Also, did you check is your Coorutine not running few times? I understand that you are sure that you Starts it only one time? Do you reciving Single Debug.Log("Timer starts") calls...
If not: Just add bool which will block multiple repetitions....
bool m_coorutineIsAlreadyGoing = false;
then in line where you starting coorutine, just change for:
if (!m_coorutineIsAlreadyGoing) StartCoroutine(powerUp(other))
And in Your Coorutine:
IEnumerator powerUp(Collider2D player)
{
m_coorutineIsAlreadyGoing = true;
//rest of your code...
m_coorutineIsAlreadyGoing = false;
}
Hope that will help, let me know!