GameObject fields evaluate to null, but they are actually assigned and working
I've been browsing for days on the internet, desperately trying to solve this problem. Basically, I have a simple game manager script in my game which needs references to game objects that are part of the UI. I have called them UITutorialText, UITutorialImage, UIGamePaused and they are, respectively, a Text which shows up as a tutorial, an image for the tutorial and a text which gets displayed when the game is paused. I assign them through drag and drop in the inspector, but whenever I check their value in the script they evaluate to null, even though the script is actually working and I never get any NullReference error. This happens in the Awake, Start or Update method in the same way. Here are the relevant bits of code (I omitted parts which do not use those fields):
[...]
// UI elements to control
public GameObject UITutorialText;
public GameObject UITutorialImage;
public GameObject UIGamePaused;
[...]
void Awake()
{
// setup reference to game manager
if (gm == null)
gm = this.GetComponent<NewGameManager>();
currentSceneName = SceneManager.GetActiveScene().name;
// setup all the variables, the UI, and provide errors if things not setup properly.
setupDefaults();
}
void setupDefaults()
{
[...]
// friendly error messages
if (UIGamePaused == null)
Debug.LogError("Need to set UIGamePaused on Game Manager.");
if (UITutorialText == null)
Debug.LogError("Need to set UI Tutorial Text on Game Manager.");
if (UITutorialImage == null)
Debug.LogError("Need to set UI Tutorial Image on Game Manager.");
[...]
}
As you can see, variables are given a value in the inspector:
But then I see 3 errors in the console which mean that I have 3 null pointers:
What might I be getting wrong? Thanks in advance!
EDIT: I ran some tests and I discovered something very strange: if I log the value of one of the fields (UITutorialText) every time that Update runs, I get null, then a correct value, then null, then a value, then null and so on... It looks like something is changing those variables at every Update cycle, but I only use them in this very script.
Hum, is your class named NewGame$$anonymous$$anager ?
or is NewGame$$anonymous$$anager a component on the same game object?
I understand gm is a static member to reference a sort of singleton. Also, you don't need to specify this here : gm = this.GetComponent();
gm = GetComponent<NewGame$$anonymous$$anager>();
// you may prefer to use this
gm = FindObjectOfType<NewGame$$anonymous$$anager>();
$$anonymous$$y class is named NewGame$$anonymous$$anager and this script file is attached to a GameObject called Game$$anonymous$$anager. Therefore, Game$$anonymous$$anager has a script component named NewGame$$anonymous$$anager.
Yes, it's kind of a "dirty" singleton. I know I don't need to, but I love specifying it anyway, it makes the code look clearer to my eyes... is it bad practice? Co$$anonymous$$g from a Java background, I don't really know.
Ok, got it. Singletons are definitely handy. In Unity, there are different implementations possible, with time, I figured this one was the best fit most of the time.
private static Game$$anonymous$$anager _instance;
public static Game$$anonymous$$anager Instance
{
get
{
if (_instance == null)
{
_instance = (Game$$anonymous$$anager)GameObject.FindObjectOfType(typeof(Game$$anonymous$$anager));
if (_instance == null)
{
GameObject go = new GameObject("Game$$anonymous$$anager:Singleton");
_instance = go.AddComponent<Game$$anonymous$$anager>();
}
}
return _instance;
}
set
{
_instance = value;
}
}
void Awake()
{
Instance = this;
}
void OnDisable() // optionally reset instance to null if component is disabled
{
Instance = null;
}
void Destroy() // optionally reset instance to null if object is destroyed
{
Instance = null;
}
Here's another little optimisation you can do, which may lead to identify the problem.
When you want to "contraint" a member to a specific type, like say an UI.Text, it's always better to set the member type specifically, ins$$anonymous$$d of just Transform or GameObject. Like
public Text UITutorialText;
public Image UITutorialImage;
public Button UIGamePaused;
Then, if you happen to need access to the GameObject itself, you can always access the .gameObject property.
You can also use stack trace to see what is changing the property.
That is what I was initially doing, I then switched to GameObject thinking it could have been a possible cause of the error and never switched back... I'll change it, thanks for pointing it out.
Thanks for the stack trace suggestion too, I didn't even think about it (how stupid of me): I'll try debugging with it and let you know.
Ok, it looks like the problem is not strictly related to these particular fields: if I put a random new GameObject for testing purposes (public GameObject NullTest), whatever object from the hierarchy I drop in this field behaves in the same way: null on one iteration, correct value in the next one. Like if there were 2 concurrent instances of the same script...
I'll continue investigating... I hope that I'll finally find a solution to post here.
Answer by davidevolta98 · Dec 12, 2016 at 01:33 PM
Ok, I am so stupid... I just found the solution. It looked like there was another instance of the same script running, so I disabled every game object except for my GameManager and tried to enable back the others one by one... the same script was attached in a Background Camera nested into my Main Camera... removing that fixed everything.
Sorry for the time I have made you uselessly waste.
Hey, no worries, here's a little trick that'll save you time :
in the hierarchy view search field, type "t:nameOfYourClass". It'll filter the view to display the objects using that component.
Cheers
nameOfYourClass is enough when typed case sensitive
Your answer
Follow this Question
Related Questions
Scale of object does not update properly with public variable 1 Answer
Unity 4.1.5 is not showing certain public variables in the inspector 1 Answer
,Unity Custom Inspector CreateInspectorGUI redraw on change 1 Answer
Public fields not showing in inspector 1 Answer
Setting value in inspector does not update script. 0 Answers