Search Unity

Coroutine Wait is Being Inconsistent

Discussion in 'Scripting' started by Gabe-Tucker, Dec 31, 2019.

  1. Gabe-Tucker

    Gabe-Tucker

    Joined:
    Nov 26, 2015
    Posts:
    94
    Hey there! Here's my code.
    Code (CSharp):
    1. public IEnumerator LoadAfterTime(string newScene, Vector3 startLocation)//CAN BE ACCESSED FROM OTHER SCRIPTS
    2.     {
    3.         StartCoroutine(FadeScript.FadeOut());
    4.         Debug.Log("WAITING FOR " + (FadeScript.fadeTime + 0.5f) + " SECONDS");
    5.         yield return new WaitForSeconds(FadeScript.fadeTime + 0.5f);//so it can finish black before switching scenes//WHY DOES THIS WAIT FOREVER WHEN CALLED FROM ANOTHER SCRIPT
    6.         Debug.Log("DONE, LOADING " + newScene);
    7.         dataClasses.SpawnInformation.spawnLocation = startLocation;
    8.         dataClasses.SpawnInformation.directedScene = newScene;
    9.    
    10.         SceneManager.LoadScene("LoadingScene", LoadSceneMode.Single);
    11.     }
    When I go into the hole or click the button, the same coroutine is called. Both times, it prints WAITING FOR (time), but only upon going into the holes does it make it past the WaitForSeconds yield, which is the same time in both situations. I'm confused as to why there's this inconsistency. You can see this demonstrated in the GIF I attached. Any feedback is appreciated. Thanks!
     

    Attached Files:

    Last edited: Dec 31, 2019
  2. Gabe-Tucker

    Gabe-Tucker

    Joined:
    Nov 26, 2015
    Posts:
    94
    Hey everyone, any feedback would be appreciated. I've still managed to find nothing on this issue. Thank you!
     
    Last edited: Dec 31, 2019
  3. Gabe-Tucker

    Gabe-Tucker

    Joined:
    Nov 26, 2015
    Posts:
    94
    I wrote that this was an unrelated error, but I was mistaken when I wrote that. The error still very much exists. Sorry for the misclarification!
     
  4. dgoyette

    dgoyette

    Joined:
    Jul 1, 2016
    Posts:
    4,196
    I can only think of a few reasons that WaitForSeconds wouldn't continue at around the expected time:
    • You're setting Time.timeScale to 0 in one of your scenes, in which case WaitForSeconds will never continue. Use WaitForSecondsRealtime if you need to wait while paused, or find some other non-time-based value to wait for.
    • You're stopping the coroutine for some reason, or destroying the object that started the coroutine.
    • You're passing in a very high number of seconds to wait, but given your logging, that doesn't seem likely.
    My assumption would be that it's because of timeScale. Are you adjust timescale?
     
  5. Gabe-Tucker

    Gabe-Tucker

    Joined:
    Nov 26, 2015
    Posts:
    94
    Hi dgoyette! I don't think I'm doing anything with my timeScale, and I doubt there would be any timescale changes considering how everything is happening in the same scene. I also don't think that I'm destroying or altering the coroutine in any way differently than I am for the first time. I also tried WaitForSecondsRealtime and it didn't seem to change anything. Sorry to throw down your ideas- I understand this is a really difficult problem and I really appreciate the suggestion!
     
  6. dgoyette

    dgoyette

    Joined:
    Jul 1, 2016
    Posts:
    4,196
    Oh, just to be sure, you're calling your coroutine with StartCoroutine, and not just calling it like it was a method?

    Code (CSharp):
    1. // Like this:
    2. StartCoroutine(LoadAfterTime(s,v));
    3.  
    4. // NEVER like this:
    5. LoadAfterTime(s,v);
    I think if you just called the coroutine like it was a method, instead of with StartCoroutine, it would stop when it hit the first yield, which might explain what's going on.
     
  7. Gabe-Tucker

    Gabe-Tucker

    Joined:
    Nov 26, 2015
    Posts:
    94
    Hey! I'm actually calling the Coroutine from a separate script, which might be the problem. Here's the code in the other script:
    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. public class AdminTransport : MonoBehaviour
    4. {
    5.     public string sceneToLoad;
    6.     public SceneInteractions sceneInteractions;
    7.  
    8.     public void ButtonClick()
    9.     {
    10.         StartCoroutine(sceneInteractions.LoadAfterTime(sceneToLoad, new Vector3(0, 0, 0)));
    11.     }
    12. }
    13.  
     
  8. dgoyette

    dgoyette

    Joined:
    Jul 1, 2016
    Posts:
    4,196
    Hmm. That approach makes me a little uncomfortable, but a quick google search seems to indicate that it shouldn't be a problem. It's probably worth just verifying that, though, but having ButtonClick() call a plain old 'void' function in your sceneInteractions, and allow sceneInteractions to do the StartCoroutine call.

    The following link looks similar to what you're doing, and it seems like there really shouldn't be an issue with Script A calling StartCoroutine on a method in Script B: https://forum.unity.com/threads/running-startcoroutine-from-a-non-monobehaviour.233817/ So, this remains a bit confusing.
     
  9. Gabe-Tucker

    Gabe-Tucker

    Joined:
    Nov 26, 2015
    Posts:
    94
    Huh! I managed to get it to work with a workaround. I called a separate function in the second script from the first script, then that function did its own StartCoroutine. Thanks for all the help!! I appreciate it :)
     
  10. dgoyette

    dgoyette

    Joined:
    Jul 1, 2016
    Posts:
    4,196
    Well, that's kind of what I thought should happen, but the other links I found made it seem like your original approach was okay. Anyway, glad it's working.