So in my game, I have a gameobject with a bunch of scripts loaded on it, and one of the scripts, grabs all of the other scripts on the same object during start(). I’ve been told that finding these scripts in awake() fixes it, and it does seem to fix it, but it’s impossible to know for sure because it happens extremely randomly and is rare.
It’s a null reference error. and the error happens inside fixedupdate with the variables that grabbed my scripts inside start(), which, fixedupdate(), should ONLY be running after my start() function gets called. So what gives? Why does this happen?
Keep in mind, this NEVER has happened once in the editor, only during a server build, and I start my game through the editor at least 50+ times a day with absolutely no errors relating to this. I can’t verify it for sure, but it seems to only happen after a fresh build, and seems to go away after that? Extremely weird and I hope someone can give an explanation as to why this happens.
ScriptA has a Rigidbody reference that it initializes using GetComponent in its Start method.
ScriptB has a reference to ScriptA and wants to access its Rigidbody field in its Start method.
public class ScriptA : MonoBehavior {
public Rigidbody body;
void Start() {
body = GetComponent<Rigidbody>();
}
}
public class ScriptB : MonoBehavior {
public ScriptA scriptA;
void Start() {
Rigidbody scriptABody = scriptA.body;
scriptABody.velocity = Vector3.zero;
}
}
There’s the possibility here that Unity will call ScriptB’s Start method before ScriptA’s, which means ScriptA’s body field is currently null at the time ScriptB tries to reference it, resulting in a NullReferenceException when ScriptB tries to set the velocity.
In your case, you happened to get lucky with the undefined execution order in the editor, but not in the build.
There is a consistent behavior with Awake and Start, however. No matter what order scripts are executed in, all Awake methods will be called before the first Start method.
We can change our ScriptA and ScriptB situation to this, which would solve the problem:
public class ScriptA : MonoBehavior {
public Rigidbody body;
void Awake() {
body = GetComponent<Rigidbody>();
}
}
public class ScriptB : MonoBehavior {
public ScriptA scriptA;
void Start() {
Rigidbody scriptABody = scriptA.body;
scriptABody.velocity = Vector3.zero;
}
}
Now it is guaranteed that ScriptA’s body field will be initialized by the time ScriptB references it.
Try to follow this convention as a general rule:
Use Awake to initialize a script’s own data.
Use Start to initialize data that is accessed from other scripts.