AddComponent passing variable before Start/Awake

How can we AddComponent() to a gameObject and passing variable to it, but the component can read the variable in Start() / Awake()?
It seems Start / Awake already ran in AddComponent line… I just want it check once so it seems not optimised having it checked in Update()

MyClass mc = AddComponent("MyClass") as MyClass; 
mc.myVar = 1;

In MyClass.cs:

public class MyClass : MonoBehaviour
{
  public int myVar = 0;
  void Start ()
  {
    if (myVar == 1)
    {
      // Do something
    }
  }
}

p.s. I tried Add component in one line with parameters, but it seems do nothing to Start() / Awake();

Credit to Dani Phye for the starting solution, but it’s a giant wall of code that can be stripped down to the part the concerns people looking for the answer:

this.gameObject.SetActive(false);

var mc = this.AddComponent<MyClass>; 
mc.myVar = 1;

// Awake of MyClass will only get called when the object is re-enabled below. Voila!
this.gameObject.SetActive(true);

This answer is a little late, but I was using NonGamingCoder’s solution and I ran into a problem when I needed a component to create another component in Awake, but that third object initialization required the values I initialized in the second object during awake. So basically I needed something “before awake.” I found a sorta hacky solution that seems to work pretty well though - and it is a general enough pattern it can be adapted to lots of different things once you get the hang of it.

Imagine we start with a GameManager object, and on GameManager’s Awake we want to make a Player, which then makes a FishingPole - yet we want the player and the fishing pole to both have a reference to the GameManager at the beginning of their awakes. Then the code would be:

public class GameManager : MonoBehaviour
{
    public Player player;
    public Awake()
    {
        GameObject playerObject = new GameObject();
        player = Player.AddPlayerComponent(playerObject, this);
        player.gameObject.name = "Player";
    }
}

public class Player : MonoBehaviour
{
    public GameManager gameManager;
    public FishingPole fishingPole;

    public static Player AddPlayerComponent(GameObject objectAddingPlayerTo, GameManager gameManager)
    {
        objectAddingPlayerTo.SetActive(false);

        Player player = objectAddingPlayerTo.AddComponent<Player>() as Player;

        // Variable initialization goes here - 
        // All of this will be called before Player's awake because
        // the object holding the Player component is currently not active.
        player.gameManager = gameManager;

        objectAddingPlayerTo.SetActive(true);

        return player;
    }

    public Awake()
    {
        GameObject fishingPoleObject = new GameObject();

        // We can use the gameManager variable here because it will already be initialized
        // since akwake isn't called until sometime after we called
        // objectPlayerAddingTo.SetActive(true);
        fishingPole = FishingPole.AddFishingPoleComponenet(fishingPoleObject, this, gameManager);
        fishingPole.gameObject.name = "Fishing Pole";
    }
}

public class FishingPole: MonoBehaviour
{
    Player player;
    GameManager gameManager;

    public static FishingPole AddFishingPoleComponent(GameObject objectAddingFishingPoleTo, Player player, GameManager gameManager)
    {
        objectAddingFishingPoleTo.SetActive(false);

        FishingPole fishingPole = objectAddingFishingPoleTo.AddComponent<FishingPole>() as FishingPole;
        fishingPole.player = player;
        fishingPole.gameManager = gameManager;

        objectAddingFishingPoleTo.SetActive(true);

        return fishingPole;
    }
    public Awake()
    {
        // This will begin with player and gameManager already pointing to the other objects
    }
}

Dude,

I’ve been hitting this kind of thing recently. It’s not the nicest solution, as in it’s quite ugly, but here it goes:

  1. Create objects during Awake()
  2. Initialize during Start()

Eg.

public class MyClass : MonoBehaviour
{
    public int myVar = 0;

    public void Awake()
    {
       // We want to see what order things are getting called...
       Debug.Log(string.Format("{1}@{0} Awake", name, GetType().Name));
    }

    public void Start()
    {
        Debug.Log(string.Format("{1}@{0} Start", name, GetType().Name));

        if (myVar == 1)
        {
            // Do something
        }
    }
}

public class MyClassHost : MonoBehaviour
{
    private MyClass _mc;

    public void Awake()
    {
       Debug.Log(string.Format("{1}@{0} Awake", name, GetType().Name));
       _mc = AddComponent<MyClass>();
    }

    public void Start()
    {
       Debug.Log(string.Format("{1}@{0} Start", name, GetType().Name));

        // By the time we get to here, MyClass.Awake will have been called.
        _mc.myVar = 1;
    }
}

Like I said, it’s not the nicest solution, you would normally want to do this all in one go, and if it wasn’t unity, you’d do this in the constructor.

Also, Unity is going to call Start(), so don’t do it yourself. Utilise Unity’s lifecycle and let Unity do it’s magic. Run this code as-is, and watch the console. You’ll see Start() gets called, but maybe not in the order you were expecting.

Disclaimer: No warranty is provided.

Why do you only let script initialization happen in Start / Awake ?
Make public method Init(), and call it after you have set everything you wanted.
Or even call it with those parameters

Turns out the way you do it is simple…
Set the object to inactive before you addcomponent, and the awake function will only play when you set it to active again.