Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

[Solved] - simple X seconds wait before launching your script ? (Beginner)

Discussion in 'Scripting' started by krousty_bat, Feb 16, 2016.

  1. krousty_bat

    krousty_bat

    Joined:
    Oct 9, 2012
    Posts:
    60
    Hello

    I wanted to create a simple X seconds pause before launching my script, so I tried to write this, but it's obviously wrong, because nothing is launched anymore now. Can you explain me what I should have done please?
    Thx

    Code (CSharp):
    1.     private float startWait = 3;
    2.  
    3. // -------------------------------------------------------------------
    4.     void Start()
    5.     {
    6.         float startCount = startWait- Time.time;
    7.         if (startCount < 0f)        
    8.         {
    9.         // execute the rest of my my script
    10.  
    Edit: "better script logic"
     
    Last edited: Feb 16, 2016
  2. krousty_bat

    krousty_bat

    Joined:
    Oct 9, 2012
    Posts:
    60
    so I tried this

    Code (CSharp):
    1.         float sc = startWait;
    2.  
    3.         while (sc > 0f)
    4.             {
    5.             sc = startWait - Time.time;
    6.         }
    7.  
    8.         if (sc <= 0f)
    9.        {
    10.        // execute the rest of my my script
    11.  
    But it make Unity freeze :(...
    (probably stuck in the while loop, even if I don't get why)
     
  3. krousty_bat

    krousty_bat

    Joined:
    Oct 9, 2012
    Posts:
    60
    So now, i'm trying to go with a Coroutine

    Code (CSharp):
    1.     private bool itIsTrue = false;
    2.    
    3. // -------------------------------------------------------------------
    4.     void Start()
    5.     {
    6.  
    7.         Debug.Log( itIsTrue );
    8.         StartCoroutine ("Wait");
    9.  
    10.         if (itIsTrue)
    11.         {
    12.         // execute the rest of my my script
    13.  
    14.     IEnumerator Wait()
    15.     {
    16.         yield return new WaitForSeconds (startWait);
    17.         itIsTrue = true;
    18.     }
    19.  
    Can someone tell me why after the coroutine is placing the itIsTrue to true, thinga are not working ?
    Thx
     
  4. Gnatty

    Gnatty

    Joined:
    May 17, 2012
    Posts:
    77
    I haven't got a lot of time right now, but regarding your first example, the Start() method is only executed once.
    It's likely the time has passed and not reached the desired time in Start.
    Try moving it to the Update() method.
     
  5. Puyol

    Puyol

    Joined:
    Nov 2, 2015
    Posts:
    3
    I think Gnatty is right about the Start function. As is it called only once, you probably never reach 0 in startWait. You should use Update()
    In addition, I'm not 100% sure, but you should use Time.deltaTime, to decrease startWait the time it spent between each update
     
  6. DanielQuick

    DanielQuick

    Joined:
    Dec 31, 2010
    Posts:
    3,137
    It's simpler to use Invoke.

    Code (csharp):
    1. private float startWait = 3f;
    2.  
    3. void Start() {
    4.     Invoke("Initialize", startWait);
    5. }
    6.  
    7. void Initialize() {
    8.     // Your code
    9. }
     
    Last edited: Feb 16, 2016
    Puyol likes this.
  7. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,199
    So this code:

    Code (CSharp):
    1.         float sc = startWait;
    2.  
    3.         while (sc > 0f)
    4.             {
    5.             sc = startWait - Time.time;
    6.         }
    7.  
    8.         if (sc <= 0f)
    9.        {
    10.        // execute the rest of my my script
    11.  
    Time.time doesn't change during a frame, and it's 0 on the first frame. So if that's in start, your code is:

    Code (csharp):
    1.  while(sc > 0f) {
    2.     sc = startWait - 0f;
    3. }
    Which is an infinite loop.

    In this code:

    Code (CSharp):
    1.     private bool itIsTrue = false;
    2.    
    3. // -------------------------------------------------------------------
    4.     void Start()
    5.     {
    6.  
    7.         Debug.Log( itIsTrue );
    8.         StartCoroutine ("Wait");
    9.  
    10.         if (itIsTrue)
    11.         {
    12.         // execute the rest of my my script
    13.  
    14.     IEnumerator Wait()
    15.     {
    16.         yield return new WaitForSeconds (startWait);
    17.         itIsTrue = true;
    18.     }
    19.  

    The coroutine is started, but that doesn't block the execution of Start from continuing - so the if(itIsTrue) check happens before the WaitForSeconds is finished running.

    The coroutine is the correct way to go, but you don't need an itIsTrue bool - just stick the code you want to run after some seconds in the Coroutine:

    Code (CSharp):
    1.     void Start()
    2.     {
    3.         StartCoroutine (Wait());
    4.     }
    5.  
    6.     IEnumerator Wait()
    7.     {
    8.         yield return new WaitForSeconds (startWait);
    9.         // execute the rest of your script
    10.     }
    11.  
    As an added bonus, if you turn Start into an IEnumerator, Unity will run it as a coroutine for you. You can't really do this with any other methods, but for your use case, this is perfect:

    Code (csharp):
    1. IEnumerator Start() {
    2.     yield return new WaitForSeconds(startWait);
    3.     //run code
    4. }
     
    Puyol and krousty_bat like this.
  8. krousty_bat

    krousty_bat

    Joined:
    Oct 9, 2012
    Posts:
    60
    Thx Everyone,
    I took a break after being very frustrated spending so much time understanding this :)...
    and now i'm ready to read all this and get it done !

    I guessed that my code was not called anymore because it was in a "Start"
    but the problem is that the code was not meant to be in a void Update, because it should not be repeated! :)

    Thx again !
     
  9. krousty_bat

    krousty_bat

    Joined:
    Oct 9, 2012
    Posts:
    60
    Hey Baste

    Thx for your time and explantations.
    I used your 1st method, because I don't get yet why i should transform my Start in IEnumerator, and who knows, maybe i'll need some other stuff later in my start.

    So, it's working, but I have two extra question
    My code is calling a Coroutine, and it's now called from the Coroutine Wait()... is it alright to do so ?
    and should I write at the end of if a StopCoroutine("Wait");

    Code (CSharp):
    1.     void Start()
    2.     {
    3.         StartCoroutine (Wait());
    4.     }
    5.  
    6.     IEnumerator Wait()
    7.     {
    8.         yield return new WaitForSeconds (startWait);
    9.         // execute the rest of your script
    10.  
    11.         StartCoroutine ("SpawnLoop");
    12.         StopCoroutine("Wait");
    13.     }

    Thx.
     
  10. Vedrit

    Vedrit

    Joined:
    Feb 8, 2013
    Posts:
    514
    The reason you may want to turn Start into an IEnumerator is because then you can use yield return WaitForSeconds(time) before the rest of the coroutine is executed, thus pausing the execution of your script.
    Alternatively, you could use Invoke and not have to deal with coroutines and WaitForSeconds, like this
    Code (csharp):
    1. int waitTime;
    2. void Start()
    3. {
    4.    Invoke("function", waitTime);
    5.    //This will execute function 'function' after waiting waitTime in seconds, unless designated otherwise
    6. }
    7.  
    8. void function()
    9. {
    10.    //do stuff, like calling or invoking other functions
    11. }
    Personally, I don't much like coroutines, but they do have their uses.

    You could use your script as you have posted, but rather than using
    Code (csharp):
    1. StopCoroutine("Wait");
    you could just use
    Code (csharp):
    1. yield break;
     
    Puyol and krousty_bat like this.
  11. passerbycmc

    passerbycmc

    Joined:
    Feb 12, 2015
    Posts:
    1,739
    if you want to pause it, you would have to set enabled to false in the start of your Start method than return it to true after the coroutine has run.

    even know you have paused Start with the courutine Update will still run like normal unless enabled = false
     
  12. krousty_bat

    krousty_bat

    Joined:
    Oct 9, 2012
    Posts:
    60
    Thx a lot for all these comments and help.

    I don't have yet the skills or knowledge to think about "Pausing" my game yet. I will have first to move to simple task like launching the game again after the death of the player and being able to start the level from scratch.

    I'm learning by doing a "flappy bird" type of game, I don't look for being original here, just learning by myself to do a 2d prototype in unity (i'm originally an animator, so scripting C# si far from my orignal skills ;).

    So thx again for the help and comments, my protoype is moving forward, it's always rewarding :).
     
  13. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,199
    No. The coroutine is finished, there is no need to stop it. Your StopCoroutine call does exactly nothing.

    yield break in the end of an IEnumerator is like an empty return statement in the end of a void method. No point.
     
  14. krousty_bat

    krousty_bat

    Joined:
    Oct 9, 2012
    Posts:
    60
    I see, so I can instead use StopCoroutine to stop another one,
    like when a character is dead, stop spawning stuffs that are in a coRoutine dedicated to spawn (this is just an example).

    Code (CSharp):
    1.     public void StopSpawn()
    2.     {
    3.         StopCoroutine("SpawnLoop");         //stops another Coroutine spawning function
    4.     }
     
  15. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,199
    Pretty much, yes.
     
  16. JacobGames

    JacobGames

    Joined:
    Dec 2, 2015
    Posts:
    12
    Hi, you might want to check out another solution to make delays


    We were frustrated with writing coroutines, and the only simple, one-line, solution was to use Invoke, but it cannot delay methods with parameters, so we created a tool that allows you to have more control on delays and at the same time it is easy to use.


    Your code would be:
    Code (CSharp):
    1. private float waitTime = 3f;
    2.  
    3. void Start() {
    4.     SuperInvoke.Run(waitTime, YourMethod);
    5. }
    6.  
    7. private void YourMethod() {
    8.     // code of your script
    9. }