When attempting to run the script shown below, I keep getting a NullReferenceException at line 41, and then again at line 85 when I try to call that method. From looking up lots of similar problems online, I think I’ve narrowed it down to the problem being that for some reason door1Image (and door2Image / door3Image based on some tests I ran) are null. Which I think means that for some reason " door1.GetComponent() " is not properly assigning the image to the door1Image variable? The script is attached to an empty game object, is attempting to alter the transparency of 3 other game objects, and is having the method in it called from a toggle on a 4th toggle game object. Here are some pictures showing generally how things are arranged in my hierarchy / inspector. What I’m aiming for is that when the toggle checkmark is clicked, it sets all the doors to be semi-transparent by setting their image color alpha to 65%, and then sets them back to fully opaque when toggled again. I have a script which I thought would do this attached to an empty “GameController” object, which I dragged into the “On Value Changed” field of the toggle, and selected the method I want to call when the toggle is toggled. I haven’t often set things up this way (having an empty object with scripts attached), but one of the tutorials I followed for an earlier project organized things this way so I’m trying it out more. I’m still learning, but have spent about two hours today searching online, and changing things without making any progress in learning what I’m doing wrong here. Especially since I did something very similar on a previous project with no issue. So far I’ve tried removing all Prefabs from the scene (previously the doors were Prefabs and I read some threads about Prefabs not playing nice with scripts?), changing how I assign the doors in the script between using “Find” vs. dragging and dropping in the Inspector, changing using temporary “var” variables in the method for all of these to now using “proper” variables declared at the start of the class, moving chunks of the code from “Start()” to my custom method and back again, etc. EDIT: Also just tried changing all references to “Image” to “SpriteRenderer” and using “GetComponent<SpriteRenderer()>” since I just realized the doors are actually Sprites, not Images, but still get the same error… I put some “dummy” bools in different parts of the script to confirm that the “void Start()” does run, and the method does in fact get called when the toggle is clicked. Code below, this is in a 2D game scene, if that matters. I still haven’t made use of all the variables I’ve set up since I’ve gotten stuck on this part:
script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
public class Toggles : MonoBehaviour
{
public float doorTransparency = 0.65f;
public bool transparentDoors = false;
public bool doorHistory = false;
public bool viewGameRules = false;
public bool testingRun = false;
public bool isDoor1ImageNull = false;
public bool isDoor1ColorNull = false;
public GameObject transparentDoorsToggle;
public GameObject doorHistoryToggle;
public GameObject viewGameRulesToggle;
public GameObject door1;
public GameObject door2;
public GameObject door3;
public GameObject transparentDoorsNotes;
public GameObject GameRules;
private Image door1Image;
private Image door2Image;
private Image door3Image;
private Color door1Color;
private Color door2Color;
private Color door3Color;
// Start is called before the first frame update
void Start()
{
door1 = GameObject.FindWithTag("Door1");
door2 = GameObject.FindWithTag("Door2");
door3 = GameObject.FindWithTag("Door3");
door1Image = door1.GetComponent<Image>();
door1Color = door1Image.color;
door2Image = door2.GetComponent<Image>();
door2Color = door2Image.color;
door3Image = door3.GetComponent<Image>();
door3Color = door3Image.color;
testingRun = true;
}
// Update is called once per frame
void Update()
{
}
private void FixedUpdate()
{
}
public void ToggleTransparentDoors()
{
/*
var tempImage1 = door1.GetComponent<Image>();
var tempColor1 = tempImage1.color;
var tempImage2 = door2.GetComponent<Image>();
var tempColor2 = tempImage2.color;
var tempImage3 = door3.GetComponent<Image>();
var tempColor3 = tempImage3.color;
*/
if (door1Image == null)
{
isDoor1ImageNull = true;
}
if (door1Color == null)
{
isDoor1ColorNull = true;
}
if (!transparentDoors)
{
testingRun = true;
door1Color.a = doorTransparency;
door2Color.a = doorTransparency;
door3Color.a = doorTransparency;
door1Image.color = door1Color;
door2Image.color = door2Color;
door3Image.color = door3Color;
transparentDoors = true;
}
else
{
testingRun = false;
door1Color.a = 1f;
door2Color.a = 1f;
door3Color.a = 1f;
door1Image.color = door1Color;
door2Image.color = door2Color;
door3Image.color = door3Color;
transparentDoors = false;
}
}
}
I really appreciate any insight into pointing me in the right direction to keep digging!
UPDATE: After swapping all usage of “Image” to “SpriteRenderer” and then fixing the typos I introduced while doing that, it all seems to work as intended! Looks like the root cause was me trying to treat a SpriteRenderer as an Image in the script
Thanks anyway for the helpful threads in this forum I looked through while troubleshooting this!
No doubt Kurt is going to come in with his usual post. But in a nutshell a Null Reference exception just means what it’s trying to access isn’t there.
Looking at your code, I find it a bit odd that you have public gameobject variables - that you have set up in your inspector - and then you immediately try and find them again by tag? To me it appears these searches aren’t finding what they’re looking for, but they’re also probably not needed? Try commenting them out, see if solves your issue.
Is door1Image what is null? Find out by placing a Debug.Log.
What is supposed to assign a value to door1Image? The line “door1.GetComponent()” must be returning null. Why is it returning null? According to the docs, GetComponent:
Which would seem to suggest that whatever GameObject assigned to door1 doesn’t have an image component attached.
Debug.Log the value of door1 and verify that it is the GameObject you expect it to be.
Yes, that was me being sloppy when I was troubleshooting and tried setting them up 2 different ways, then left the redundancies up after it didn’t work. Thanks for the tips though! Luckily I discovered the very silly mistake I made and solved the issue, more details in an edit to my main post.
I missed this reply while editing my main post, but this is exactly what the problem was, thanks! Turns out I was trying to alter some SpriteRenderers, not some Images, so that’s why it couldn’t find any Image component.
For next time, what is the way I would use Debug.Log for a similar problem? In this case I made some public bools set to false and tried adding lines of “customBool = true” to different parts of the code to see if they got executed or not by looking at the inspector while running the game, is it similar to that?
Debug.Log will print messages to the console. Add them like so:
Debug.Log("Running Code");
Will print “Running Code” in the console if that line is executed. This is an easier way to check what is running and when then a bunch of public bools.
You can print the value of objects too:
Debug.Log("My Object: " + anObject);
Will print “My Object: MyGameObject” if the variable “anObject” is assigned a GameObject called “MyGameObject”. It will just print "My Object: " if it is not.
First, everything that @bobisgod234 says above for sure.
But second, here’s my standard debug log blurb:
To help gain more insight into your problem, I recommend liberally sprinkling Debug.Log() statements through your code to display information in realtime.
Doing this should help you answer these types of questions:
is this code even running? which parts are running? how often does it run? what order does it run in?
what are the values of the variables involved? Are they initialized? Are the values reasonable?
Knowing this information will help you reason about the behavior you are seeing.
You can also put in Debug.Break() to pause the Editor when certain interesting pieces of code run, and then study the scene
You could also just display various important quantities in UI Text elements to watch them change as you play the game.
If you are running a mobile device you can also view the console output. Google for how on your particular mobile target.
Here’s an example of putting in a laser-focused Debug.Log() and how that can save you a TON of time wallowing around speculating what might be going wrong:
For an interactive game where causing the failure requires continued careful play, debug log is far more powerful than attaching a debugger which freezes the game and locks the screen up.
Thanks very much for this advice!
I’m making much more steady progress now, and how some Debug.Log() indicators for when my main game items get clicked / selected / etc., and it’s really helping things go smoothly with the quick feedback