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;
weaponPreFab
basically 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 GameObject
that 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!
ShooterWeapon needs to be attached to a game object in order for the Awake and Start methods to be hit on game start. GetComponent Returns the componend (Class) from the given object.
Just think of it like a map of [Component, class]
If you're like me and don't want to attach components (Unitys way of attaching classes) you can just drive everything by logic
@jmgek thanks for the reply! I really appreciate it!
I don't think I quite follow. ShooterWeapon
is attached to currentWeaponPrefab
, which is a GameObject
. currentWeaponPreFab is attached to PlayerController
. currentWeaponPreFab.GetComponent<ShooterWeapon>()
does return an instance. The docs say
Returns the component with name type if the game object has one attached, null if it doesn't. ..
Which suggests to me that my ShooterWeapon
is attached to a GameObject
, but still I'm not seeing Start or Attach fire. Is it that the ShooterWeapon
is nested? Do only the first level components get their Start()
and Attach()
methods called?
Answer by UnityCoach · Jul 06, 2017 at 01:01 PM
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.
@UnityCoach - That was it, thank you! I thought that by assigning the prefab to currentWeapon
it implicitly instantiated the object. Good to know!
Your answer
Follow this Question
Related Questions
The script I copied from the Summer 2020 Week 1 Tutorial, not working for me... 0 Answers
Instantiate Prefab From Script Inside A Canvas 2 Answers
Changing Values in Inspector Only Takes Effect After Playing the Scene Twice? 0 Answers
how to update a specific script from a prefab to the in scene object 1 Answer
Changing a Prefab's Text component seems to be broken. 1 Answer