Start() and Awake() not called on MonoBehaviour

Hello all,

I’ve been writing software professionally for ~ 6 years but this is my first foray into game programming and Unity is the first game framework I’ve ever used. I’v done a couple of the tutorials (docs and tutorials are great so far btw!) and am messing around with the shooter tutorial after I finished it, trying to make some of my own enhancements. I’m sure I’m not following best practices and not doing things in the ideal way but it’s part of my learning process.

That being said here is what I am seeing.

I have a script that contains a class called ShooterWeapon. It looks like this:

public class ShooterWeapon : MonoBehaviour {

    public GameObject weaponPreFab;
    public float fireRate;
    public int energyUse;  

    private float nextFire;

weaponPreFabbasically contains the ui of the weapon projectile which I create later with Instantiate
I have a pre fab called basicBlaster and it has a ShooterWeapon script compoent

I also have a PlayerController script. It looks like this:

public class PlayController : MonoBehaviour {

public GameObject currentWeaponPreFab;

private Rigidbody body;
private ShooterWeapon currentWeapon;

    body = GetComponent<Rigidbody>();
    currentWeapon = currentWeaponPreFab.GetComponent<ShooterWeapon>();

I have a GameObjectthat has a PlayerController script component. In that
component I set currentWeaponPrefab to the basicBlaster prefab I mentioned
above.

Now… what I am seeing is that Start() and Awake() in my ShooterWeapon are not being
called. strangely enough however my call in PlayerController.Start() that does

currentWeapon = currentWeaponPreFab.GetComponent<ShooterWeapon>();

does, to my surprise return a reference to a ShooterWeapon. It has some properties populated and I have no idea where the values come from (not what I set them to in Start() for that class. I’ve inserted debugging lines and set up debug breakpoints in Start() and Awake() and none have been hit.

Has anyone seen behaviour like this? the docs seem to imply Awake() is always run so I’m not sure whats going on here. Any advice or suggestion would be very much appreciated. Thanks much!

1 Like

Hi, it may be confusing, here’s how it works :

when you reference a GameObject, or any other component type for that matter, you can assign it a Prefab.
Prefabs are nothing but serialised GameObjects. They do not exist in the scene, thus, they don’t receive any of the MonoBehaviour messages (Awake, Start, Update).
If you assigned an object from the scene to your currentWeaponPreFab reference, it would receive those messages, but you’d miss the advantages of Prefabs.

When you instantiate a Prefab’s GameObject , it creates a copy of the object, with all its components.
If you want to access the component on the copy, you need to keep a reference to the instantiated object and use GetComponent on it to find the new instance. Something in the like of :

currentWeapon = ((GameObject)Instantiate (currentWeaponPreFab)).GetComponent<ShooterWeapon>();

Also, messages are only called on active game objects, and some messages like Start and Update are only called on enabled components.

You can also reference a ShooterWeapon instead of a GameObject, that way you are sure that the prefab bears that component.
Then you can always access the .gameObject property to instantiate a copy.

public ShooterWeapon currentWeaponPreFab;

currentWeapon = ((GameObject)Instantiate (currentWeaponPreFab.gameObject)).GetComponent<ShooterWeapon>();

ps : check out my website for more tips & tricks.