Startup Manager

From Unify Community Wiki
(Difference between revisions)
Jump to: navigation, search
(added obsolete notice)
 
(3 intermediate revisions by one user not shown)
Line 1: Line 1:
 +
'''Notice: You can set script execution order in Unity 3.4 and newer. Making this system obsolete.'''
 +
 +
 
There is currently no built-in way to manage the order in which scripts start up.  To a certain extent you can get around this by putting more important or prerequisite code into Awake(), but this doesn't solve the problem and if you're entirely likely to run into the same problem again.
 
There is currently no built-in way to manage the order in which scripts start up.  To a certain extent you can get around this by putting more important or prerequisite code into Awake(), but this doesn't solve the problem and if you're entirely likely to run into the same problem again.
  
Line 10: Line 13:
 
* 1. Put StartupManager on a game object in your scene somewhere
 
* 1. Put StartupManager on a game object in your scene somewhere
 
* 2. Derive your scripts (or at least the ones which you need to control the order they start in) from BaseBehaviour instead of MonoBehaviour
 
* 2. Derive your scripts (or at least the ones which you need to control the order they start in) from BaseBehaviour instead of MonoBehaviour
* 4. Profit
+
* 3. Profit
  
==C# - StartupManager.cs==
+
=== StartupManager.cs ===
 
<syntaxhighlight lang="csharp">
 
<syntaxhighlight lang="csharp">
 
using UnityEngine;
 
using UnityEngine;
Line 62: Line 65:
 
</syntaxhighlight>
 
</syntaxhighlight>
  
==C# - BaseBehaviour.cs==
+
=== BaseBehaviour.cs ===
 
<syntaxhighlight lang="csharp">
 
<syntaxhighlight lang="csharp">
 
using UnityEngine;
 
using UnityEngine;
Line 81: Line 84:
 
      
 
      
 
     [HideInInspector]
 
     [HideInInspector]
        public bool _initialized = false;
+
    public bool _initialized = false;
  
 
     public virtual void Initialize() {
 
     public virtual void Initialize() {
Line 88: Line 91:
 
     }
 
     }
  
public virtual void Start () {
+
    public virtual void Start () {
 
         if( StartupManager.Instance != null )
 
         if( StartupManager.Instance != null )
 
             StartupManager.Instance.registerStartup( this );
 
             StartupManager.Instance.registerStartup( this );
 
         else
 
         else
 
             Initialize();
 
             Initialize();
}
+
    }
  
 
     public virtual void LateUpdate() {
 
     public virtual void LateUpdate() {
Line 105: Line 108:
 
Here is an example of a BaseBehaviour derived class.
 
Here is an example of a BaseBehaviour derived class.
  
==C# - TestClass.cs==
+
=== TestClass.cs ===
 
<syntaxhighlight lang="csharp">
 
<syntaxhighlight lang="csharp">
 
using UnityEngine;
 
using UnityEngine;
Line 129: Line 132:
  
  
Feel free to ask me any questions regarding this script
+
Feel free to ask me any questions regarding this script. -Ryan Scott
  -Ryan Scott-
+
 
 +
[[Category: Legacy]]

Latest revision as of 07:08, 14 November 2018

Notice: You can set script execution order in Unity 3.4 and newer. Making this system obsolete.


There is currently no built-in way to manage the order in which scripts start up. To a certain extent you can get around this by putting more important or prerequisite code into Awake(), but this doesn't solve the problem and if you're entirely likely to run into the same problem again.

The startup manager is a singleton class that calls an initialization function on participating objects created in the last frame (or at startup) in the order dictated by their priority variable. Participating classes must be derived from the provided BaseBehaviour class (which in turn derives from MonoBehaviour as per usual). This class registers with the startup manager singleton in Start() which then calls Initialize() on it at the begining of the next frame (again, in the appropriate order).

The BaseBehaviour.priority member is a float. This was a design decision to allow for plenty of tweaking.

BaseBehaviour derived objects which do not find the StartManager instance (e.g. because it is not present in the scene) will call Initialize themselves in Start()

Contents

[edit] Basic Usage

  • 1. Put StartupManager on a game object in your scene somewhere
  • 2. Derive your scripts (or at least the ones which you need to control the order they start in) from BaseBehaviour instead of MonoBehaviour
  • 3. Profit

[edit] StartupManager.cs

using UnityEngine;
using System.Collections;
 
public class StartupManager : MonoBehaviour {
 
    public static StartupManager Instance;
 
    public bool debug = false;
 
    ArrayList componentList = new ArrayList();
 
    void Awake() {
        Instance = this;
    }
 
    void Update () {
        if( componentList.Count <= 0 )
            return;
 
        if( debug )
            Debug.Log( "StartupManager: Update()" );
 
        // Call Initialize() on everything
        componentList.Sort();
 
        foreach( BaseBehaviour behaviour in componentList ) {
            if( behaviour != null && behaviour._initialized == false )
                initializeObject( behaviour );
        }
 
        componentList.Clear();
    }
 
    public virtual void registerStartup( BaseBehaviour behaviour ) {
        if( debug )
            Debug.Log( "Registering " + behaviour + " @ priority " + behaviour._StartupPriority );
 
        componentList.Add( behaviour );
    }
 
    public void initializeObject( BaseBehaviour behaviour ) {
        behaviour.Initialize();
        behaviour._initialized = true;
    }
 
}

[edit] BaseBehaviour.cs

using UnityEngine;
using System.Collections;
 
public class BaseBehaviour : MonoBehaviour, System.IComparable {
 
    public float _StartupPriority = 0f;
 
    public int CompareTo( object obj ) {
        if( obj is BaseBehaviour ) {
            BaseBehaviour thisObj = (BaseBehaviour) obj;
            return _StartupPriority.CompareTo( thisObj._StartupPriority );
        }
 
        return 0;
    }
 
    [HideInInspector]
    public bool _initialized = false;
 
    public virtual void Initialize() {
        //Debug.Log( _StartupPriority + ": In Inititialize()" );
        _initialized = true;
    }
 
    public virtual void Start () {
        if( StartupManager.Instance != null )
            StartupManager.Instance.registerStartup( this );
        else
            Initialize();
    }
 
    public virtual void LateUpdate() {
        if( StartupManager.Instance == null ) {
            _initialized = true;
        }
    }
}

Here is an example of a BaseBehaviour derived class.

[edit] TestClass.cs

using UnityEngine;
using System.Collections;
 
public class NetworkGame : BaseBehaviour {
 
    void Awake() {
        _StartupPriority = 10f;
    }
 
    override public void Initialize() {
       Debug.Log( "Starting @ Priority " + _StartupPriority );
    }
}

A few things of note:

  • If you define start you'll need to use override in the normal way
  • The member BaseBehaviour._initialized can be checked to see if the object has been initialized
  • _StartupPriority is exposed in the editor so you can change it there for scene/object specific startup priorities
  • Groups of BaseBehaviour derived objects created in a particular frame will be dealt with by StartupManager in the same way as at the start of the scene


Feel free to ask me any questions regarding this script. -Ryan Scott

Personal tools
Namespaces

Variants
Actions
Navigation
Extras
Toolbox