Coroutine stopping for seemingly no reason.

Unable to post source code, if I can’t solve it in the next day or so I’ll make an example I can post…
I have a GameObject with the hierachy:

Player

VRTrackers

FadeCanvas

FadeImage
Player
VehiclePlayer

In this game I am switching Player and VehiclePlayer active and inactive depending on whether the player is in a vehicle or not. When I do this the coroutine (which is started by a component of FadeCanvas) is stopped after the next yield return null… My question is why is deactivating/activating Player or VehiclePlayer causing the coroutine to suddenly stop even though the active state of VRTrackers and it’s children is never changed? Is this the expected behaviour?

The coroutine is to do with fading and unfading the view, it is a child of the player to make it easier for the world space UI used for fading to stay infront of the player’s camera.

Here is the coroutine:

public IEnumerator FadeIn(float pTime, Action pOnFinished = null)
{
   // Determine absolute alpha change per second required.
   float deltaAlphaPerSec = 1f / pTime; // Rate of alpha changed required to complete task is total time from 0->1. [1 / seconds to fade out then in]

   // Start at 1 alpha & enable fade image gameObject.
   image.gameObject.SetActive(true); //tested: issue happens with or without this.
   image.color = new Color(image.color.r, image.color.g, image.color.b, 1f);

   // Work down to minimum alpha removing deltaAlphaPerSec units per second.
   while (image.color.a > 0f)
   {
       // Remove deltaAlphaPerSec * Time.deltaTime units of alpha this frame.
       image.color = new Color(
           image.color.r,
           image.color.g,
           image.color.b,
           Mathf.Max(image.color.a - (deltaAlphaPerSec * Time.deltaTime), 0f)
       );
       yield return null;
   }

   // Disable fade image gameObject.
   image.gameObject.SetActive(false); //tested: issue happens with or without this.

   // Finished event invoke.
   if (pOnFinished != null)
       pOnFinished?.Invoke();
}

Summary: When a child’s GameObject has SetActive(false) called on it the parent’s coroutines are abruptly stopped even though the parent remains active. Why does disabling a child gameObject cause the coroutines from an object that was not deactivated to stop?

Edit #1: The FadeImage gameObject gets activated and deactivated but the component that starts the coroutine is on the FadeCanvas gameObject. This doesn’t seem to be a problem because the fade system works on another system in the game that doesn’t enable/disable any children of the Player (aside from FadeImage). (Edit again: I removed the code that enables/disables FadeImage and the same issue still occurs.)

Coroutines are stopped when the gameObject they are on is Disabled. Since the script itself is on the Player, it stops when being disabled. Starting the coroutine from another script does not change which gameObject it is actually a part of.

Edit: For an actual solution to the problem, have you tried Enabling the object, and then starting to coroutine?

1 Like

Well no, this does definitely not happen. I just tried and you can disable and enable child objects however you want, that won’t affect the parent’s coroutines at all. But you haven’t even posted the most important part of your code. Where do you start this coroutine from?

Coroutines are started on the MonoBehaviour that you call StartCoroutine() from. So if you actually have a script inside of your Player/VehiclePlayer that says StartCoroutine(FadeCanvas.FadeIn()), then yes, it will immediately stop when Player/VehiclePlayer is set inactive. That’s expected behavior. If this is the problem, then the fix would be to implement a method StartFadeIn() on your FadeCanvas, and call that instead. StartFadeIn() then just calls StartCoroutine() directly on the FadeCanvas and should be unaffected by Player/VehiclePlayer.

I actually don’t think this is true. Of course couroutines stop when the GO they are on is disabled, but they also stop when the GameObject that started the Coroutine on another is disabled.
I’ve just created two GameObjects and started the first GO’s Coroutine by calling StartCoroutine() from the second. When the second gets disabled, the coroutine on the first stops.

1 Like

Thanks for testing this, going to have to make a simple test myself with the same hierachy. Must not be the case that just seems like the behaviour. Can’t figure out why this coroutine is stopping.

This is not the case the GameObject that has the component that calls StartCoroutine() is never activated or deactivated this is why the behaviour is throwing me off. Obviously something I’m not seeing is happening though so I’ll just have to do more debugging to see what is actually causing this.

The behaviour I’m experiencing APPEARS to be when I activate or deactivate ‘Player’ or ‘VehiclePLayer’ in the hierachy I described the coroutine that was started by a component on ‘FadeCanvas’ is abruptly stopping. Based on the behaviour I initially expected and what you describe this is clearly not what’s happening and just seems to be the case so I’ll look into it more, likely will make a simpler test project on the same Unity version. I am on the latest 2021.2 tech version.