StopCoroutine not working

I’m having a problem with StopCoroutine.

I’m calling StartCoroutine in my script called “Main_GUI” in a public function that I am calling from “Main_Script”. I am also calling StopCoroutine in “Main_GUI” in a public function that I am also calling from “Main_Script”. The coroutine is not stopping and I know for sure that the stop function is being called. Does anyone have an ideas what might be causing this?

Just for clarification: coroutines are bound to the game object that starts them and can only be stopped again on the game object that starts them.

so if the start and stop happen on the same object, no problem.
If they don’t you need to implement a public stop function on the object that is called by the other object

Oh, so in this situation:

ObjectA has ClassA attached to it
ObjectB has ClassB attached to it

ClassB calls a public function in ClassA that starts a coroutine, the coroutine would be attached to ObjectB?

If so what about this situation:

ObjectA has ClassA attached to it
ObjectB has ClassB attached to it
ObjectC has ClassC attached to it

ClassC calls a function in ClassB which eventually calls a function in ClassA that starts a coroutine. The coroutine would be attached to ObjectC?

No, if B calls a function on A that starts a coroutine on A, then the coroutine is related to the gameobject of A.

Ok, that’s what I originally thought.

Right now I have ClassB calling a public function in ClassA to start a coroutine and when ClassB decides that ClassA shouldn’t finish the coroutine, ClassB calls a public function in ClassA that calls StopCoroutine. But the coroutine doesn’t stop for some reason. Hopefully that makes sense.

How do you know that the coroutine does not stop and how does your exact code for the starting, the stopping and the coroutine method itself look?

Sorry I took so long to respond, my company moved buildings and I’ve been busy at home.

I realize this isn’t the best code, I needed to get a lot of stuff done in a short period of time. I am now in the process of going back and fixing all the stuff that I slapped together before.

Anyways, I call StartGameOverUI after the fireworks for beating a level play and I call StopGameOverUI if the player starts a new level before the scores have finished rolling up and the grade appears.

public IEnumerator ShowGameOverUI(float waitTime)
   {            
      Debug.Log("ShowGameOverUI");
      yield return new WaitForSeconds(waitTime);
         
      shownEndScore = 0;
      shownTimeBonus = 0;
      shownTurnsBonus = 0;
      shownPowerupBonus = 0;
      shownTotalScore = 0;
      
      gameOverScreen = true;
      gameOver = false;
      
      ArrayList GUIScript;
      Component[] GUIComponents;
      
      if(Score>0  turnsLeft > 0  gameTime > 0f || MainScript.playMode == 4)
      {   //win
         GUIComponents = winGUI.GetComponentsInChildren(typeof(GUIQuadObj)) ;      
      }
      else
      {   //lose
         GUIComponents = loseGUI.GetComponentsInChildren(typeof(GUIQuadObj)) ;
         loseGUI.audio.Play();         
      }
      
      GUIScript = new ArrayList();
      for(int i = 0; i < GUIComponents.Length; i++)
      {
         GUIScript.Add((GUIQuadObj)GUIComponents[i]);
      }
      
      for (int i=0;i<GUIScript.Count;i++)
      {
         (GUIScript[i] as GUIQuadObj).Visible = true;
      }
      if(Score>0  turnsLeft > 0  gameTime > 0f || MainScript.playMode == 4)
      {
         for (int i=0;i<StampQuads.Length;i++)
         {
            StampQuads[i].Visible = false;
         }
      }
      
      GUIQuadObj tempQuad;
      if(turnsLeft <= 0)
      {
         tempQuad = TimeUp.GetComponent(typeof(GUIQuadObj)) as GUIQuadObj;   
         tempQuad.Visible = false;
      }
      else if(gameTime <= 0)
      {
         tempQuad = NoFlips.GetComponent(typeof(GUIQuadObj)) as GUIQuadObj;   
         tempQuad.Visible = false;
      }
      
      
      if(Score>0  turnsLeft > 0  gameTime > 0f || MainScript.playMode == 4)
      {
         AchievementScript.CheckLevelsComplete(MainScript.LevelNum);
         
         float lerper = 0f;
         if(!muteSE)
         {
            ScoreCounterSE.audio.Play();
         }
         while(lerper < 1f)
         {
            yield return new WaitForSeconds(0.04f);
         
            shownEndScore = (int)Mathf.Lerp(0f,(float)Score,lerper);
            lerper+=0.04f;
         }
         
         shownEndScore = Score;
         
         if(timeLeftBonus>0)
         {
            lerper = 0f;
            if(!muteSE)
            {
               ScoreCounterSE.audio.Play();
            }
            while(lerper < 1f)
            {
               yield return new WaitForSeconds(0.04f);
            
               shownTimeBonus = (int)Mathf.Lerp(0f,(float)timeLeftBonus,lerper);
               lerper+=0.04f;
            }
            shownTimeBonus = timeLeftBonus;
         }
         
         if(turnsLeftBonus>0)
         {
            lerper = 0f;
            if(!muteSE)
            {
               ScoreCounterSE.audio.Play();
            }
            while(lerper < 1f)
            {
               yield return new WaitForSeconds(0.04f);
            
               shownTurnsBonus = (int)Mathf.Lerp(0f,(float)turnsLeftBonus,lerper);
               lerper+=0.04f;
            }
            shownTurnsBonus = turnsLeftBonus;
         }
         
         if(numPowerupsBonus>0)
         {
            lerper = 0f;
            if(!muteSE)
            {
               ScoreCounterSE.audio.Play();
            }
            while(lerper < 1f)
            {
               yield return new WaitForSeconds(0.04f);
            
               shownPowerupBonus = (int)Mathf.Lerp(0f,(float)numPowerupsBonus,lerper);
               lerper+=0.04f;
            }
            shownPowerupBonus = numPowerupsBonus;
         }
         
         lerper = 0f;
         if(!muteSE)
         {
            ScoreCounterSE.audio.Play();
         }
         while(lerper < 1f)
         {
            yield return new WaitForSeconds(0.04f);
         
            shownTotalScore = (int)Mathf.Lerp(0f,(float)totalScore,lerper);
            lerper+=0.04f;
         }
         
         ScoreCounterAS.Stop();
         shownTotalScore = totalScore;
            
         yield return new WaitForSeconds(0.5f);
         Debug.Log("about to stamp");
         StampQuads[stampNum].Visible = true;
         
         StampQuads[stampNum].ClearAnimation();
         StampQuads[stampNum].AnimateFrom(0.2f, null, null, null, "Scale", new Vector2(2f,2f), "easing", Ani.AnimationEasingType.LinearEasing);
         StampQuads[stampNum].StartAnimation (Ani.Animate.OneShot, null, null, null);
         
         
         yield return new WaitForSeconds(0.12f);
         
         if(!muteSE)
         {
            StampQuads[0].audio.Play();
         }
      }
      else
      {
         AchievementScript.saveToMaster();
         AchievementScript.unlockAchievements();   
      }
      
   }
   
   public void StartGameOverUI(float waitTime)
   {
      StartCoroutine(ShowGameOverUI(waitTime));
      
   }
   
   public void StopGameOverUI()
   {
      Debug.Log("in StopGameOverUI");
      StopCoroutine("ShowGameOverUI");
   }

I know that it’s not stopping because I will start a new level with the printout: “in StopGameOverUI” over a second before the stamp would show up and it still shows up along with the debug statement: “about to stamp”.

Any thoughts anyone has on what the cause of the problem could be would be much appreciated as this project is almost complete and I am running out of other features to add and fix.

One problem I noticed is that when you call StartCoroutine, you are calling it with the function
StartCoroutine(ShowGameOverUI(waitTime)); syntax instead of StartCoroutine(“ShowGameOverUI”, waitTime) syntax.

The documentation says:
function StopCoroutine (methodName : string) : void
Description

Stops all coroutines named methodName running on this behaviour.

Please note that only StartCoroutine using a string method name can be stopped using StopCoroutine.

4 Likes

Yup, this is the only reason of stop not working.

Oh, thanks, I didn’t even notice that. Good thing to know for future use.

Necro Post, but google led me here so I wanted to update this since it’s one of the first google results for this problem.

Heisenburg has a great answer over at stackexchange.

You really don’t want to use the other methods (just passing a string or starting coroutines by passing the method & parameters themselves). Instead, you want to keep track of your coroutines so you can have more control to stop them or specific ones.

http://gamedev.stackexchange.com/questions/97429/stopcoroutine-is-not-stopping-my-coroutine-in-unity

My problem was that I was using this method:

StartCoroutine(MoveToPositionOverTime(myGameObject, newPosition, 30f));

public IEnumerator MoveToPositionOverTime(GameObject gob, Vector2 position, float timeToMove)

Calling StopCoroutine(“MoveToPositionOverTime”) did nothing, because I started it with that method above. So now I created a method to do it, like this:

    private IEnumerator coroutine_MoveToPositionOverTime; //Only one coroutine should be used at a time.

    private void start_UniqueSingularCoroutine_MoveToPositionOverTime(GameObject gob, Vector2 position, float timeToMove)
    {
        if (coroutine_MoveToPositionOverTime != null)
        {
            StopCoroutine(coroutine_MoveToPositionOverTime);
        }
        coroutine_MoveToPositionOverTime = MoveToPositionOverTime(gob, position, timeToMove);

        StartCoroutine(coroutine_MoveToPositionOverTime);
    }

    public IEnumerator MoveToPositionOverTime(GameObject gob, Vector2 position, float timeToMove)
    { }

This works perfectly. I just call this method now:

    start_UniqueSingularCoroutine_MoveToPositionOverTime(myGameObject, newPosition, 30f);

I have absolutely no idea why this isn’t the standard being taught. I learned the other (more popular) method, despite it being so much worse. I really wish I learned “the right way” the first time. Would have saved me an hour, since I didn’t realize it was the coroutine that was causing my bug until I chased it down & quickly realized StopCoroutine() wasn’t working as I expected.

1 Like

@CarterG81

Thank you so much for your post! I’ve been having such an issue with StopCoroutine() in my current project and your solution solved literally all of my coroutine issues. Why all tutorials teach it the other way is beyond me, because your explanation makes a lot more sense anyway?

Regardless thank you again :)!!