Invoke and Yield fail together- bug or feature?

So I ran into an issue, had some code that was working fine, called a method with Invoke on a delay. Extended the method being called and it stopped working; no errors, no warnings, the method just never got invoked. With some testing I managed to determine the offending new line: “yield WaitForSeconds(1);” Remove the yield, and it works fine.

So I put together a simple test, new scene, just attached the following script to MainCamera:

function Update()
{
    if (Input.GetButtonDown("Fire1"))
    {
        Invoke("testy",1);
    }
    if (Input.GetButtonDown("Fire2"))
    {
        Invoke("testy2",1);
    }
    if (Input.GetButtonDown("Fire3"))
    {
        Invoke("testy3",1);
    }
}

function testy() 
{
    print("testy entered");
    yield WaitForSeconds(5);
    print("testy ended");
}

function testy2()
{
    print("testy2 entered");
    //yield WaitForSeconds(5);
    print("testy2 ended");
}

function testy3()
{
    print("testy3 entered");
    while(false)
    {
        yield WaitForSeconds(0);
    }
    print("testy 3 exited");
}

Tested this in the editor on both windows and mac, same behavior each time. The invoke on testy2 works perfectly. The other two do not. Note, they don’t just not execute fully; they are never called at all, even the “entered” lines do not print.

testy3 is perhaps the revealing case - the yield can by definition never happen, since the condition is literally “false.” As I said initially, there are no errors or warnings displayed in the output, either while compiling or running. It’s just silently failing.

Thought I’d ask the community, make sure this isn’t just an “undocumented feature” or a known issue before I submit a bug report with this simple repro case.

:edit:
Thought I’d add the simple hackey workaround I’m currently using, for others who might find this question. There was a similar question already, but their solution was moving the yield out of the invoked function - which is not an option in my case.

I just added a function, DelayInvoker, which takes a string and int as params, yields WaitForSeconds(int), and then calls StartCoroutine on the string. Replaced the Invoke calls with calls to DelayInvoker, works as expected.

If someone has a more elegant workaround, by all means share.

It’s not a bug. Invoke doesn’t have any StartCoroutine functionality built in, so no, you can’t Invoke coroutines. I don’t know how feasible it would be to implement an error, because Invoking a function that happens to be a coroutine is still perfectly valid, it just won’t work as a coroutine. (A coroutine is a function that returns IEnumerator.) It may be easier to see this in C#, since JS automatically uses StartCoroutine when you call a function that’s a coroutine. In C#, you have to explicitly use StartCoroutine–calling a coroutine the way you would call a “normal” function has the same effect as using Invoke on a coroutine. (i.e., it won’t work as a coroutine.)

For what you want, there would have to be an InvokeCoroutine function, which of course doesn’t exist. But rather than Invoking a function which starts a coroutine, you can emulate Invoke’s functionality in a coroutine using WaitForSeconds instead:

function Update()
{
    if (Input.GetButtonDown("Fire1"))
    {
       StartCoroutine("Testy", 1);
    }
}

function Testy (delay : float) 
{
    yield WaitForSeconds(delay);

    print("testy entered");
    yield WaitForSeconds(5);
    print("testy ended");
}

In this way you can use StopCoroutine("Testy") to implement the functionality of CancelInvoke.