[FIXED] Coroutine issue : coroutine stopped for no reason

Hey all,

I have a weird issue with coroutines that stop for no reason. I found out that similar issues were discussed here as far back as 2012 : http://answers.unity3d.com/questions/277772/what-can-cause-a-coroutine-to-not-being-working.html

My problem is that I have a script that starts a coroutine that handles the execution over multiple frames of a character skill. The coroutine usually works fine. In some game conditions (that should have no effect at all in any way on the skill script) the skill stops working. We found out that the coroutine stops even with no calls to StopCoroutine or StopAllCoroutines. I'm positive that we have no code at all stopping the coroutine explicitely or disabling the gameObject that has the skill component. I even tried running the coroutine on another GameObject (otherObject.StartCoroutine(this.myCoroutine())).

I'm getting pretty frustrated by this bug considering there is no dependency between my skill class and the classes that handles the game state that seems to be triggering the bug, and there are no calls to stop the coroutine anyway.

If anyone's got any idea or knows if this has been logged to the issue tracker and is known about by the Unity people, let me know. Or if you guys have any idea of what I could check out in my code...

Edit : the issue was caused by an Invoke("method", time) call with a time value that was a NaN value. Doing this eventually caused all coroutines to stop and break all subsequent coroutines. If you run through a similar issue, check your Invoke calls.

You could start by posting your coroutine...

2 Likes

I can but it won't give you any pointer as to why the coroutine stops. The issue happens outside of the coroutine itself. The coroutines goes up to the first yield statement, and then it is never entered again. The coroutine is stopped, the same way it would be if I had deactivated the gameObject it's running on via another script. But it's not the case that the gameObject was deactivated. And I didn't call either StopCoroutine or StopAllCoroutines.

The following code works for most of the game, until it doesn't. We can reproduce the bug in a variety of ways but every single thing we activate or deactivates in the game state that can trigger the bug has absolutely no link to the skill script. When the coroutine doesn't work, it never passes the first yield statement. This code is simplified but what I removed is a bunch of bool variables being sate appropriately and stuff like that

//coroutine in the base class
private IEnumerator Cast()
    {
        yield return new WaitForSeconds(CastingTime.value);

        Character.WithdrawMana();
        Character.OnSkillCast(this);//fire an event

        transform.rotation = Quaternion.Euler(0, Angle, 0);

        Coroutine currentdocastcoroutine = MasterController.instance.StartCoroutine(DoCast());//coroutine in the derived class

        yield return currentdocastcoroutine;

        if (canStartCoolDown)
            StartCoolDown();

        yield return new WaitForSeconds(AfterCastDelay.value);

        IsCasting = false;

    }

edit : Also, if I comment out the first yield statement, in case the CastingTime value is super large, the coroutine goes up to the second yield statement and then is stopped in the same way.

So if I understand correctly, your coroutine goes up to line 14 then (sometimes) stops there?
What is your "DoCast" Coroutine?

Maybe someone has experienced exactly this and will be able to give you advice.

Otherwise, I get the feeling this will be a really tough one to crack without a repro. Can you simplify your scenario and teach us how/provide script to reproduce the problem?

1 Like

No errors or warnings in the console?

The DoCast coroutine is an empty virtual IEnumerator. Classes that derive from my abstract skill class can implement their own logic there to instantiate objects and such. This coroutine isn't an issue I can easily add a debug line in the while loop to check if the DoCast is running forever but that is not the case.

@eisenpony : It is a tough one for sure. I can't walk you through all the scenarios that can reproduce the bug as that would mean showing the code for a LOT of objects. The main thing though is : none of these objects do anything with the skills! It is uncanny! For example, setting a Vector3 property in one of my skill's projectile will cause the projectile to call a delegate upon arrival. The update function checks the distance every frame and calls the delegate when distance < 0.1f. This code is fairly simple but will cause a skill's Cast coroutine to stop for no reason AT SOME POINT later in the game. We can fix the issue but we have no idea why removing the Vector3 property fixes the issue. The projectile doesn't even do anything about the skill beyong calling the destination reached delegate!

@A.Killingbeck no warnings or errors. We found that the coroutine was stopped by noticing the IsCasting bool is never set to false and then adding a bunch of debugs in the coroutine itself to see when it stops working. The answer is : at some point in the game, the coroutine will never go beyong the first yield statement in the coroutine.

The bug happens when our game transitions from team deathmatch to free-for-all but removing the code that does this transition, the bug still happens.

I think there's a ghost in the machine. Crazy bug.

I'm at the point where I might just try an alternative to coroutines to check whether the bug happens or not. If anyone knows of a good library for implementing coroutine-like tasks, I could try that.

Does the bug persist if you yield the raw IEnumerator from DoCast?

IEnumerator cast = DoCast();
while (cast.MoveNext())
    yield return cast.Current;

I'll try it after my lunch but at first we were using the method name as a string to start and stop the coroutine and the bug was still happening.

Some progress was made, apparently creating a new script for the skill and copy/pasting the exact same code from the skill that triggered the bug solved the issue. The original script was created on a Mac while all the other skills who don't seem to trigger the bug, including the copy/pasted script, were created on a Windows machine. Is it possible that some character encoding or something that has to do with the Mac screwed up the coroutine execution ?

I sincerely hope not.

Nope, reproduced the bug again -_-

More info : all coroutines seem to have stopped, not just the skills. How can all coroutines even be stopped? Is it possible that a coroutine's yield cause Unity to throw a hidden exception and just stop calling all coroutines?

Edit: Once the bug happens, any coroutine that we try to start subsequentely will not get past the first yield statement

1 Like

Are you sure you don't have any Stop(All)Coroutine calls anywhere? Are you switching scenes by chance?

Yeah I'm positive, the coroutine doesn't stop because of a StopCoroutine, StopAllCoroutine or GameObject.SetActive(false) call. The bug occurs on our game server which doesn't switch scene.

[quote=“DoomSamurai”, post:3, topic: 582650]
We can reproduce the bug in a variety of ways
[/quote]
What kinds of things can you do to initiate this weird behavior?

[quote=“eisenpony”, post:18, topic: 582650]
What kinds of things can you do to initiate this weird behavior?
[/quote]

Sometimes, executing a skill will do it. Sometimes we have to change from team deathmatch to free for all, sometimes its just a matter of running around in the scene and waiting a few minutes. It’s nothing consistent. The only thing that is consistent is the effect : all coroutines stop and no coroutines can be started again.

I was hoping for some code but I guess you haven't narrowed it down.