When is Awake called on an inactive gameobject

Hi,

I want to be able to configure the properties of a prefab instance (which is created at runtime), prior to its Awake calls (I am using Unity 4.2 btw). My first thought was to deactivate the prefab before instantiating it and this seems to work fine. However, the documentation states

Awake: This function is always called before any Start functions and also just after a prefab is instantiated. (If a GameObject is in-active during start up Awake is not called until it is made active, or a function in any script attached to it is called.)

The bold part is what concerns me. While testing this, calling a function or setting a property on a script did not cause Awake to be called.

So, in which cases is Awake called on an inactive gameobject ?
Am I interpreting the documentation wrong ?
Is the documentation wrong ?
Is there a bug in Unity 4.2 ?

Edit: Note that the part of the documentation that this was taken from describes what happens during a scene load (couldn’t find this type of information for runtime instantiation). So it might be that inactive gameobjects are treated differently during during scene load and later. However, I want to be sure so that I don’t build a solution which will break in later versions of Unity.

Any help would be appreciated.

Thanks,

Ben

Let’s make a small experiment.

Create empty scene and add two game objects to it with names “ObjectA” and “ObjectB”. Then add appropriate scripts to them with the same names.

ObjectA.cs:

public class ObjectA : MonoBehaviour {
	
	public GameObject objectB;

	void Start () {
        objectB.GetComponent<ObjectB>().Test();
       //objectB.GetComponent<ObjectB>().ForceActivation();
	}
}

ObjectB.cs:

public class ObjectB : MonoBehaviour {

	void Awake () {
		Debug.Log("Awake");
	}
	
	void Start () {
		Debug.Log("Start");
	}
	
	void OnEnable() {
		Debug.Log("OnEnable");
	}
		
	void OnDisable() {
		Debug.Log("OnDisable");
	}
		
	public void Test() {
		Debug.Log("Test");
	}
	
	public void ForceActivation() {
		this.gameObject.SetActive(true);
		Debug.Log("ForceActivation");
	}

}

Uncheck active mark of ObjectB on scene. And than drag this object in to the “Object B” field inside ObjectA component in your Unity Editor’s Inspector view.

Run scene. ObjectB remains inactive. And you will see output in the console:

Test

ObjectB is still inactive and will be remain so. Now activate ObjectB in the Inspector View and you’ll see in console:

Awake
OnEnable
Start

Next change Start() function in ObjectA.cs to this:

	void Start () {
        //objectB.GetComponent<ObjectB>().Test();
        objectB.GetComponent<ObjectB>().ForceActivation();
	}

Run scene again. ObjectB will be activated and console output will be:

Awake
OnEnable
ForceAcivation
Start

This bold part is actually not clear, and here is a clarification :
http://forum.unity3d.com/threads/unityevent-disabled-objects-awake-failure.267241/

As Tim C says in this thread : “If a GameObject is inactive during start up Awake is not called until it is made active, or an Unity lifetime function in any script attached to it is called. (OnEnable, OnCollisionEnter)”

That means that calling normal functions is not going to “awake” your script.

Something that seems to work for me. Useful when I have GameObjects that are inactive when the game starts, but I still want to be able to call methods scripts attached to those GameObjects.

Create a new abstract class:

    /// <summary>
    /// Helps with the problem that Awake() and Start() don't run on inactive GameObjects, when a method of the objects
    /// is called.  
    /// </summary>
    public abstract class UIModalStarter : MonoBehaviour
    {
    
        protected bool hasWokenUp = false;

        protected abstract void Awake();
        protected abstract void Start();
    
        protected void WakeUp()
        {
            if (!hasWokenUp)
            {
                Start();
                Awake();
                hasWokenUp = true;
            }
        }
        
    }

Derive from this, instead of MonoBehavior. In public methods (that you want to call when the GameObject the script is attached to is inactive), call WakeUp(). In Start() and Awake(), test to make sure that the flag has not been set.

public class ScriptAttachedToInactiveGameObject: UIModalStarter
{
  ...
  protected override void Awake()
  {
      if (hasWokenUp)
      {
          return;
      }
      ...
  }

  protected override void Start()
  {
      if (hasWokenUp)
      {
          return;
      }
      ...
  }

  public void DoSomething() {
      WakeUp();
      ...
  }
  
}

Not elegant, but it seems to work, and I understand it.