Search Unity

Start() is called before Awake() and other Start() issues.

Discussion in 'Scripting' started by hoesterey, Dec 8, 2018.

  1. hoesterey

    hoesterey

    Joined:
    Mar 19, 2010
    Posts:
    659
    Edit: It looks like the Start() Awake() issue reported was caused by an editor refresh issue where it lost the reference to a script due to renaming but did not report the error until it was shutdown and reloaded. I'll update the bug accordingly.

    I also want to raise a long standing issue with Startup order in general: Start() being called latently in projects under high load.

    Having just shipped http://bowtoblood.com/index.html for the PSVR in order to run at framerate we had to instantiate all objects that would be used at scene start. We ran into an issue where if we instantiated objects and then disabled them Start would not be called on all objects (It seams unity only calls start on a set number of objects per frame), thus we had to create systems to track when Start was called on all objects() before allowing the game to proceed. Start order should be 100% deterministic in Unity.
     
    Last edited: Dec 8, 2018
  2. hippocoder

    hippocoder

    Digital Ape

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    Unity runs all awakes first, then all starts second. I recall there was a bug with this in older version of Unity, but not 2018.3 beta (as of beta 12) as far as I know. Got a case number?

    Ref: https://docs.unity3d.com/Manual/ExecutionOrder.html

    Remember, if pooling, start won't be called on inactive objects. This is not a bug:
     
  3. hoesterey

    hoesterey

    Joined:
    Mar 19, 2010
    Posts:
    659
    Sorry I edited the original Awake() Start() issue and sent unity an email. It was caused by an editor caching issue and fixed by a restart.


    Per this comment:
    • Start: Start is called before the first frame update only if the script instance is enabled.

    I would argue that if the behavior I'm seeing is not considered a bug it should be. Here is an example of what happens:

    Behavior I'm seeing
    You instantiate 3000 game objects in a frame while the screen is black.
    Awake() is called on all those objects.
    Start() is called on SOME of the objects.
    You disable the objects <- start was NOT called on all of the objects.


    The dev side workaround is as follows:
    You instantiate 3000 game objects in a frame while the screen is black. (but need to do so out of scene and in a grid pattern to avoid collisions as you can't immediately disable the objects)
    Awake() is called on all those objects.
    Start() is called on SOME of the objects.
    You track ALL instantiated objects in some way e.g. they add to a list during Awake().
    You increment some counter when Start() is called on each object.
    When the counter is equal to the number of objects you disable them.


    The above solution is not acceptable for a number of reason. The largest being physics, as the physics collisions do process before Start() is called on all the objects. So to get around that issue you now have to do something like create objects outside your scene in a "grid" so they don't collide with each other. Again this Start() issue is only when a project is under heavy load. Start order should always be deterministic.

    Some solutions that could be implemented on the unity side:
    -Start() is always called if the object was enabled when it was instantiated into the scene.
    -OnAwakeComplete() callback that is triggered when ALL components in scene have awaken for that frame (allowing us to finalize startup behavior before pooling)


    Thanks.
     
  4. orb

    orb

    Joined:
    Nov 24, 2010
    Posts:
    3,037
    Have you profiled the time it takes to create those 3000 objects? If it takes longer than a frame update you'll have objects instantiating on both sides of that update, making some skip Start() until the next frame. Of course there could still be bugs around :/

    If you want faster handling of their Start() methods you don't actually use that. You can pool them together inside a manager object and call them all at once from its Start() method. It makes a massive difference in processing time, since even empty standard methods cause a noticeable hit in CPU time used.

    If you want it even faster there's ECS. Huge job to convert, probably.
     
  5. hoesterey

    hoesterey

    Joined:
    Mar 19, 2010
    Posts:
    659
    We pooled everything inside a manager object. My point is that if you Instantiate all the objects with a manager and then disable those objects with the manager Start() will only be called on some of the objects. We could call our own version of start (assuming we knew Awake() was done being called) and there are workarounds but we shouldn't have to write a workaround for something that is this core to the engine.

    The ECS conversion will be easy on our end as in order to hit framerate in PSVR we basically built an engine around the engine that is spookily similar to the ECS feature unity is bringing online. 60fps in two eyes on a ps4 is hard. E.g. All our objects "Register" to our a single update loop, everything is handled by managers, we have an "EntityComponent" and all our components are just data. (Data oriented design stuff) You also can't ever dip in FPS on console in VR so we even had to disable the GC and do our own manual cleanup between levels (and if the game runs for several hours without the player progressing (never happens outside of stress tests) and we detect memory issues we dip to black with a quick "Buffering" to cleanup and avoid a crash).

    We will look at using ECS for a project once it has matured and unity is willing to put their stamp of approval on it for production. Right now we are looking at engine upgrades during prototype and I'm still seeing some of the issues we had to workaround to ship Bow to Blood.

    I'd like to remove some of the more hacky workarounds and get closer to the metal on things like pooling and memory management.
     
  6. orb

    orb

    Joined:
    Nov 24, 2010
    Posts:
    3,037
    Yes, I'd love to see better tooling for ECS (like in Tiny and then some) as soon as possible. It would make starting to use it less of a chore, and drive more people to start projects with ECS. I'm just seeing a mountain of ick to walk up in its current state :p
     
    Lurking-Ninja and hippocoder like this.