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. Dismiss Notice

Question Change ScriptExecutionOrder at runtime

Discussion in 'Scripting' started by Nit_Ram, Sep 7, 2023.

  1. Nit_Ram

    Nit_Ram

    Joined:
    May 8, 2016
    Posts:
    22
    Hello there,

    changing the ScriptExecutionOrder at runtime obviously is not possible because it's set at compile time. But the title summarizes what I try to achieve.
    I have Manager classes that need to be the first scripts to run their Awake() but the last scripts to call OnDestroy().

    One way of doing this would be one initializerController which runs before everything else and one terminateController which runs after all other scripts. But then again that's a bunch of added complexity and dependencies.

    Is there any other, elegant way of controlling the execution order of Event methods?
     
  2. CodeSmile

    CodeSmile

    Joined:
    Apr 10, 2014
    Posts:
    3,899
    Having to rely on ScriptExecutionOrder tends to be a code smell. More so if you need to use this at runtime.

    Instead consider your current setup. It would be solvable in the following way:
    • Manager script
      • Implements Awake() for init
      • Implements OnDestroy() for shutdown
    • All (!) other scripts (or at least those relying on Manager)
      • Implement Start() or OnEnable() for their init
      • Implement OnDisable() for their shutdown
    An alternative is where the Manager tells other scripts to run their initialize and shutdown code. Something like this:
    • Manager runs Awake()
      • Performs init stuff that must be done first
      • Gets all components with IMustAwakeAfterManager interface
      • Calls OnManagerAwoke() on each of these components
    • Manager runs OnDisable()
      • Note: I would not use OnDestroy() because this may be called too late in the shutdown cycle such that some Unity API calls are illegal or some objects that need to be shutdown by the Manager have already been destroyed.
      • Gets all components with IMustShutdownBeforeManager interface
      • Calls OnManagerShutdown() on each of these components
     
    Ryiah likes this.
  3. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,560
    Agreed. Stay away from script execution ordering stuff... just handle it yourself the way CodeSmile suggests above.
     
    Ryiah likes this.
  4. SisusCo

    SisusCo

    Joined:
    Jan 29, 2019
    Posts:
    1,104
    One small but important correction: Awake does not get executed for all loaded objects before OnEnable is executed for all of them. If you have objects A and B in a loaded scene, the initialization events will occur for them in an order more like this:
    Code (CSharp):
    1. A - Awake
    2. A - OnEnable
    3. B - Awake
    4. B - OnEnable
    5. A - Start
    6. B - Start
    So out of these three events, only the Start function would be a safe place to access the members of other components, if you use this pattern where objects setup themselves during the Awake event and the execution order is arbitrary.
     
    Nit_Ram, DragonCoder and Ryiah like this.