- Home /
Can not access Rigidbody of my camera
I am trying to access the rigidbody of my camera from my Orb script. Normally when I access a different script, I will create a public static "xxx" instance in that script/class and then I can access it from other scripts using xxx.whateverINeed. But when I try to get the rigidbody using camRB = CameraController.instance.GetComponent(); it throws a null exception error. I've done this exact thing (it seems) a hundred other times and it's never given me a problem. I don't know why it won't work. I made sure my camera has a Rigidbody in the Unity Inspector. Please. I've been working on this for so long and it doesn't make sense to me why it's not working. If anybody has any ideas or links you can provide, please help... My code:
public class CameraController : MonoBehaviour {
public static CameraController instance;
public Vector3 camOffset;
// Declare Orb handlers
Rigidbody orbRB;
Transform orbTran;
void Start ()
{
instance = this;
orbRB = Orb.instance.GetComponent<Rigidbody>(); // This works fine...
orbTran = Orb.instance.transform;
camOffset = transform.position - orbTran.position;
}
public class Orb : MonoBehaviour {
public static Orb instance;
Rigidbody orbRB, camRB;
Transform orbTran;
Vector3 direction;
// Use this for initialization
void Start()
{
instance = this;
orbRB = GetComponent<Rigidbody>();
//Debug.Log("CameraController.instance =" + (CameraController.instance).ToString());
camRB = CameraController.instance.GetComponent<Rigidbody>(); // This is where I get my error. "NullReferenceException: Object reference not set to an instance of an object Orb.Start() "
}
Answer by pako · Dec 16, 2017 at 08:48 AM
As @JedBeryll said, the problem is with the script execution order. I personally prefer to use the setting of the Script Execution Order, as a last resort, i.e. if nothing else works, and it most cases, something else does work.
In this particular case, create the CameraController
instance inside Awake()
:
public class CameraController : MonoBehaviour {
public static CameraController instance;
public Vector3 camOffset;
// Declare Orb handlers
Rigidbody orbRB;
Transform orbTran;
void Awake(){
instance = this; //the instance will now be available when Orb.Start() runs (as long as the camera is active in the scene, when Orb script loads.
}
void Start ()
{
orbRB = Orb.instance.GetComponent<Rigidbody>(); // This works fine...
orbTran = Orb.instance.transform;
camOffset = transform.position - orbTran.position;
}
//etc...
}
In a more general case, this would present a problem, if a 3rd script depended on an instance that has to be initialized in Start()
too, because it, itself depends on another instance that gets initialized in Awake()
. e.g. CustomScript.Start()
needs a reference to Orb.instance
, but it happens that CustomScript
executes before Orb
.
Yes, you could set the Execution Order to set CustomScript
to execute after Orb
. However, I would prefer to use a public variable in CustomScript
to get a reference to Orb
by dragging and dropping it in the Inspector.
Please also note that (if my memory serves me well) the order of execution of scripts may change (if not explicitly set). I believe that I've seen several cases, where script1 would execute before script2, and then suddenly, say after some change in the project, like adding more scripts, script2 would execute before script1. I haven't seen any documentation on this, it's just a matter of observation. So, what this means is, that you may currently be able to reference instances from within Start()
, but this could probably break in the future, if you initialize all instances in Start()
.
It's an issue that needs a lot of care.
@paco Yes! Thank you so much for such a thorough explanation. This worked. I put my "instance=this;" for CameraController in the Awake() and it executed without any errors. Thank you again for taking the time to explain it to me. It really helped.
Answer by JedBeryll · Dec 16, 2017 at 06:07 AM
I think the Orb script gets loaded first and it tries to access the CameraController instance before Start is called on that script. Try changing the script execution order so the CameraController is first (smaller numbers will execute first).
@JedBeryll , thank you!! This seemed to be the issue. I guess I need a deeper understanding of Unity script execution. Does this mean that if I need two scripts to be able to access each other, there will always be an issue with one initializing the other first and then the other having a null exception? Could a workaround be to do something like this?
if instance = null {instance = this;}
and just put that in the update (or some better place) of all the scripts that I need reference to? Or would putting both the initialization in Awake() always prevent a Null reference? Alternatively, is there a better way to access components of other scripts/objects? Please don't feel obligated to answer all these questions, sometimes I just type out loud to see if I can figure something out on my own.
Thank you again for your help, I got my code working (or at least that part), by putting the init for instance of the CameraController in Awake().
Don't put unnecessary things in update. There are several things you can use, Use awake for references as mentioned here: "Awake is used to initialize any variables or game state before the game starts." Then you can use them in Start, Update or anywhere really. That works for most things, however you should make sure controller classes are loaded first with execution order because for example OnEnabled may be triggered before Awake and Start.
@JedeBeryll OnEnabled may be triggered before Awake? Just to clarify in order to avoid confusion: this could only happen in different scripts, because OnEnable always follows immediately after Awake on the same script. This means that OnEnable of script 1 is always called immediately after Awake of script 1, but before Awake of script 2.
@Hello258 I'm glad that my answer solved your problem, but it seems that you are not quite clear on the points I made. So, if you need any clarifications please let me know.
@JedBeryll & @pako, thank you for your continued support! I've been doing plenty of research and now with your explanations, I feel much more comfortable with the subject. $$anonymous$$y project is co$$anonymous$$g along nicely. Thanks again for all your help! See you on the boards!