- Home /
Invoke isn't working for a function with yield?
(JavaScript) Here are two sections of code in one script attached to a cube (the 'player'):
public function ReleaseGun() { print("Started release"); weaponry.WieldedWeapon.CurrentlyReleasing = true; yield WaitForSeconds(weaponry.WieldedWeapon.ReleaseTime); if (weaponry.WieldedWeapon.CurrentlyReleasing == true) { weaponry.WieldedWeapon.currentFiresLeft = weaponry.WieldedWeapon.ReleaseCapacity; weaponry.WieldedWeapon.CurrentlyReleasing = false; print("Release successful"); } }
if (Input.GetKeyDown("r") && weaponry.WieldedWeapon.CurrentlyReleasing == false) { Invoke("ReleaseGun",0); }The if is in Update() (sorry for the sloppy code example, I don't want to try to get the code format to work with two separate pieces...it hates me). I tried Invoke with ReleaseGun just printing something. It worked and printed immediately after hitting R. I tried Invoke with everything but the "yield" in ReleaseGun. It worked, but instantly instead of WaitForSeconds working. When I add yield before WaitForSeconds, nothing happens at all. The first print isn't printed and no variables are set.
By the way, weaponry is a variable based off of a class called Weaponry. WieldedWeapon is also set to a class called Weapon, which has various weapon-related stats, including ReleaseTime, a float. The ReleaseTime of the specific weapon I was using is 3, and I printed that to verify it.
When I just regularly call the function via "ReleaseGun()", it works perfectly, but I want to invoke it so I can CancelInvoke in the middle if you change your weapon (this is like a reload system in an MOFPS).
Why does the 'yield' seem to destroy the function...?
Answer by aldonaletto · Oct 03, 2011 at 02:58 AM
Invoke is internally implemented as a coroutine, like ReleaseGun (yield transforms the whole function in a coroutine), but this shouldn't be a problem, since coroutines can start other coroutines.
Could it be possible to transfer part of the code to Update, removing the yield instruction from ReleaseGun?
if (Input.GetKeyDown("r") && weaponry.WieldedWeapon.CurrentlyReleasing == false) { weaponry.WieldedWeapon.CurrentlyReleasing = true; Invoke("ReleaseGun",weaponry.WieldedWeapon.ReleaseTime); }You still could cancel invoke while the release time wasn't ended.
Thanks! I did what you said and it's working, and I made the weapon changing function cancel the invoke and that works fine, too.
Also, thanks for fixing up the code blocks up there...I can never seem to get them right.
This format button sometimes refuses to work - I use the following tags:
(always let a blank line before the first tag)
<pre>
(code goes here)
</pre>
It has always worked fine for me in questions, answers and comments (much different from that damned format button...)
Answer by Eric5h5 · Oct 03, 2011 at 05:12 AM
You can't use yield with Invoke. I'd recommend not using Update, and instead doing everything as a coroutine. Instead of WaitForSeconds, make a function that is similar to how WaitForSeconds works but can be interrupted.
@Eric5h5, I read something about Invoke and InvokeRepeating being implemented as coroutines, but just can't remember when or where (not in the docs, I guess). If more than one Invoke/InvokeRepeating command may be active at the same time, it makes sense to use some kind of coroutine to implement these commands - you must allocate an independent control structure for each command instance, check it periodically, etc. $$anonymous$$aybe they don't use the same coroutines as us, simple mortals, but it must be a similar mechanism.