Coroutines WaitForSeconds question...
Can someone explain to me why this code is not setting my fire rate back to the correct value (the hard coded value)? I am still trying to understand Coroutines.
public PlayerController playerController;
public float totalPickupTime;
public float bonusRate = .05f;
private bool hasPickup;
void Start()
{
playerController = playerController.GetComponent<PlayerController>();
}
private void OnTriggerEnter(Collider other)
{
if (other.tag == "Player")
{
GetComponent<MeshRenderer>().enabled = false;
playerController.fireRate = bonusRate;
StartCoroutine("PickupTime");
}
}
IEnumerator PickupTime()
{
yield return new WaitForSeconds(totalPickupTime);
playerController.fireRate = .25f;
Destroy(gameObject);
}
Thanks in advance!
Answer by Matthewj866 · May 03, 2017 at 01:53 AM
Hi there.
Not sure if you're following a tutorial or something? Regardless, StartCoroutine("PickupTime");
is wrong. You cannot send it a string, it has no overload for that. You need to send it a direct call to PickupTime()
.
Example:
private void OnTriggerEnter(Collider other)
{
if (other.tag == "Player")
{
GetComponent<MeshRenderer>().enabled = false;
playerController.fireRate = bonusRate;
StartCoroutine(PickupTime());
}
}
This should fix your problem. Good luck!
Actually, I'm pretty sure there is an overload of StartCoroutine that takes a string.
https://docs.unity3d.com/ScriptReference/$$anonymous$$onoBehaviour.StartCoroutine.html
If you look at the last example on this page, it shows how you can pass in the name of a method as a string to start a coroutine. Although, I will definitely agree with you that passing it in as a method as in your example is generally the better way to go about doing it.
Well TIL, I've never done it that way and VS intellisense never showed that to me so I just sort of assumed.
Answer by hexstonepatriot · May 03, 2017 at 02:10 AM
Hey @Matthewj866 thanks for responding. Unfortunately I didn't have luck. Here is what I did:
private void OnTriggerEnter(Collider other)
{
if (other.tag == "Player")
{
GetComponent<MeshRenderer>().enabled = false;
playerController.fireRate = bonusRate;
StartCoroutine(PickupTime());
}
}
IEnumerator PickupTime()
{
Debug.Log("Is Called");
yield return new WaitForSeconds(totalPickupTime);
Debug.Log("Is called again");
playerController.fireRate = .25f;
Destroy(gameObject);
}
As you can see I added a couple print statements. The first one ("Is Called") shows up in the console. However the second one ("Is called again") never does. For reference totalPickupTime is set for 2 seconds. I am really not sure what I am doing wrong.
From what I can see, your code seems like it should be working, especially if the first debug message is appearing like you said. I'm kind of wondering if you are somehow setting totalPickupTime
incorrectly. $$anonymous$$aybe try hardcoding the number 2 into WaitForSeconds, and see if that works. If it does, it might be something with how that variable is being set.
Thanks for responding. I tried WaitForSeconds(2). Its like it is skipping some of the code because it does destroy the pickup object after 2 seconds. But it doesn't set my players fire rate nor does it print to the console.
Answer by BigScary · May 06, 2017 at 08:56 PM
I've had this problem before. In my case, something elsewhere in my code had set the object/script containing the coroutine inactive. If your script or its containing object are inactive when the coroutine should continue, it won't.