Jump to content
  • Advertisement
Felis Nigripes

C# GameObject Reference throws NullReferenceException

Recommended Posts

I'm doing a test quest.

The player gets a quest from an NPC to bring him fish.

5a8487434474d_Screenshot(149).thumb.png.f363a29d45d3e0c04163990a8ab74d80.png

Once the player picks up the fish, the original NPC gets replaced by a new one with a new conversation trigger. The NPC tells the Player "Well done" and should give 200xp.

5a8487532cd57_Screenshot(155).thumb.png.82cc90dd2cc982274fecd46adb6fe93c.png

The script tells the xp counter to go up by making a reference to the gameobject that holds the text component

 

5a8487d4eb360_Screenshot(157).png.10d5ae436c5cc02942e8c39a3ee8b834.pngBut it throws this error:

 

5a84883b16a20_Screenshot(158).png.2499e152f2471fae0753a2c307bbacc8.png

 

I'm aware that the error may hide in plain sight. I just have to sort this out, since I'm writing the AI at the same time, and the time it takes to resolve everyone of these errors is tremendous.

Plus, I think I'll learn something. I've been having trouble with some basic functionalities recently. There might be something wrong with my understanding on how programming works.

 

Glad if someone could help (:

 

 

 

Edit: I'm fully aware that the update function requires an input. I call the function in the editor when the dialogue ends, it still doesn't work.

 

Edited by Felis Nigripes

Share this post


Link to post
Share on other sites
Advertisement

It looks like your GameObject.FInd ("XPCounter") returns null. Maybe it's the wrong name (spelling error), maybe what you're looking for isn't a GameObject (I seem to remember UI things being different somehow, but it's been too long since I looked at Unity stuff to be sure).

Share this post


Link to post
Share on other sites
Just now, Lactose said:

It looks like your GameObject.FInd ("XPCounter") returns null. Maybe it's the wrong name (spelling error), maybe what you're looking for isn't a GameObject (I seem to remember UI things being different somehow, but it's been too long since I looked at Unity stuff to be sure).

The spelling is correct. I checked a dozen times. And I made the XPCounter a gameobject on purpose. Before that it was a UI, and I suspected I wouldn't be able to access that by a gameobject reference.

Maybe referencing a UI would help?

Share this post


Link to post
Share on other sites

Add a debug line after Find -- if TextHolder == null Debug.Log("Find failed") to see whether or not that's where the problem is. If might not solve the issue, but at least helps narrow down where the problem is.

Share this post


Link to post
Share on other sites

TextHolder is the only thing that can be null on that line.  The GameObject wasn't found.

"This function only returns active GameObjects." -- Documentation

Make sure the game object is in the scene (not the project) and it's active.

You should also make sure there aren't any "invisible" parts of the game object's name, such as leading or trailing spaces.

Eventually, you should think about avoiding searching for objects by name, and directly reference them by setting up those references in the scenes, prefabs, and prefab instantiation scripts.  This will increase the program's maintainability and efficiency.

Edited by Nypyren

Share this post


Link to post
Share on other sites

Or a space between "XP" and "Counter", as in "XP Counter".

It's always a good idea to check for null whenever you use a function that can return a null value, such as GameObject.Find or MonoBehaviour.GetComponentInChildren. It's part of an approach called defensive programming, and it can help avoid a lot of hard-to-find bugs.

As a side note, since you're using the Dialogue System, there might be an easier way to implement the quest than replacing the entire NPC. When the player picks up a fish, you can set a Dialogue System variable. For example, in a C# script:

DialogueLua.SetVariable("HasFish", true);

Use a single conversation on the NPC, but branch the conversation based on the value of the variable. If HasFish is false, follow one branch of the conversation. If HasFish is true, follow the other branch.

 

Share this post


Link to post
Share on other sites

I sort of figured it out:

 

@NypyrenYou were right, the script can't access the textholder if it's deactivated, even if I assign it in the editor.

Since I have my text inside the quest menu, which is deactivated by default, it can not be accessed at all.

Kinda sucks :/

 

I could of course just put the xp counter on screen at all time, but then I wouldn't have my neat little menu where all the information is stored.

Haven't decided yet wether to just roll with it or find some clumsy workaround. Any ideas?

Edited by Felis Nigripes

Share this post


Link to post
Share on other sites

Option 1:  Assign the reference in the inspector:

Check this tutorial out where he makes a public GameObject field in his C# code, and then in the inspector, drags an object into the slot.

https://unity3d.com/learn/tutorials/topics/scripting/how-communicate-between-scripts-and-gameobjects

The first 2-6 minutes or so should demonstrate what I mean.  This kind of reference will work even if the GameObject is inactive.

Basically, if you follow the same steps, you would make your TextHolder public, edit the scene or prefab(s) so that the TextHolder reference is assigned in the scene or prefab instead of using GameObject.Find at all.  When the scene or prefab is loaded, Unity will automatically assign the variable to the one you drag-and-dropped in the editor.

Option 2 is:  If you instantiate a prefab by using AssetBundle.LoadAsset, AssetDatabase.LoadAsset, Resources.Load, etc. followed by Object.Instantiate, immediately after you instantiate it, you can assign its public member variables.  If your program is well-designed, the point at which you instantiate a prefab will be a point at which you already have the references available that you want to assign to those fields.

Unfortunately, Unity does not yet let us initialize things using C# constructors.  That would be Option 3, if it becomes available in the future.

Edited by Nypyren

Share this post


Link to post
Share on other sites

I got it!

Not sure how though. I tried a public gameobject before and it didn't work.

Perhabs it's because I never removed the private reference line in the start function. Maybe this blocked out the public reference, thus creating the error. Weirdly enough I put it back in for tests sake and it still worked.

It's mysterious to me, but it's working now. Thanks for the help.

 

Just now, Tony Li said:

Or a space between "XP" and "Counter", as in "XP Counter".

It's always a good idea to check for null whenever you use a function that can return a null value, such as GameObject.Find or MonoBehaviour.GetComponentInChildren. It's part of an approach called defensive programming, and it can help avoid a lot of hard-to-find bugs.

As a side note, since you're using the Dialogue System, there might be an easier way to implement the quest than replacing the entire NPC. When the player picks up a fish, you can set a Dialogue System variable. For example, in a C# script:


DialogueLua.SetVariable("HasFish", true);

Use a single conversation on the NPC, but branch the conversation based on the value of the variable. If HasFish is false, follow one branch of the conversation. If HasFish is true, follow the other branch.

 

I will definitely try this out, thanks.

Share this post


Link to post
Share on other sites

My few cents; are you setting the reference in your Start() function? If so, perhaps try it using 'Awake', so it's done at the earliest possible time + it doesn't repeat for each game object using the script (unless you explicitly want that).

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!