Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Can I wait in Awake() or Start() until some socket operations complete?

Discussion in 'Scripting' started by Axonn, Jan 15, 2020.

  1. Axonn

    Axonn

    Joined:
    Nov 26, 2019
    Posts:
    48
    I'm still a bit new to Unity, but I've been coding for a long time before this.

    I need to perform some socket communication BEFORE the game starts. Ideally, I'd like the Start() function to not be finished until all the sockets answer back.

    If I use Start as a coroutine, then it will unfortunately not work because after the first yield, Update() starts to get called, which is not the intended behavior.

    I'm aware that I could "fake" it by performing a game-wide "if (disabled) return" in all Update() functions, or set timescale to 0. Perhaps this is the right way to do it? It feels "fake" to me because ideally I'd like to be able to, for example, in Awake call a Unity static function that blocks the engine from advancing to Start until I allow it to (say, when all my socket operations are complete).
     
  2. csofranz

    csofranz

    Joined:
    Apr 29, 2017
    Posts:
    1,556
    No. If you block Start() for a single object, you'll block the entire game with no graphics occuring and the app appearing unresponsive (that is why a single infinite loop in a component can crash the entire IDE).

    You need to go the sepaphore/coroutine way, except that Start() cannot be the coroutine itself, it will have to be a separate method, and you need to poll during Update().

    Another work-around would be to create an entire scene that takes care of the socket stull, and only switches to the main game scene once connection is established, and change to another scene if the connection failed.
     
    Axonn likes this.
  3. Axonn

    Axonn

    Joined:
    Nov 26, 2019
    Posts:
    48
    Thanks for answering! :). I didn't mean to while(true) the poor little Start() method :). But simply invoking some sort of Engine feature that waits until everything is done.

    Actually, Start can be a coroutine. What I did is to use yield in Start().

    Code (CSharp):
    1.  
    2. private IEnumerator Start()
    3. {
    4.     Time.timeScale = 1;
    5.     AudioListener.pause = false;
    6.  
    7.     //Do stuff that will eventually set IsInitialized (my own flag) to true.
    8.  
    9.     yield return new WaitUntil(() => IsInitialized);
    10.  
    11.     //Un-Pause game.
    12.     Time.timeScale = 1;
    13.     AudioListener.pause = false;
    14. }
    15.  
    Does this look sane to you?

    Mind you, this is just a prototype. I'm aware in a more complex game I may want to use some custom Update tricks.

    Your suggestion with a new Scene is really good. I assume that Scene can be made to look like a nice loading screen, right?
     
    Last edited: Jan 15, 2020
    angrypenguin and RiverExplorer like this.
  4. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,294
    Yes. You create the loading scene with the Coroutine-based Start method you've got in your script above, and one that coroutine is done you load the other scenes.
     
    Axonn likes this.
  5. csofranz

    csofranz

    Joined:
    Apr 29, 2017
    Posts:
    1,556
    My bad. I completey forgot that you can do that. Thanks for the education, Axonn, Baste!
     
    angrypenguin and Axonn like this.