- Home /
GetComponent() returns null
I can't figure out what Im doing wrong here.
I'm trying to reach an image inside a gameobect on the scene. I know the image exist.
Debug.Log(Container.transform.GetChild(i).Find("Fill - Top").transform.name);
Gives me "Fill - Top" which is the name of the gameobject im trying to reach, so that should indicated that it exist right. and in the hirarchy at runtime I see the gameobject is there with the image inside.
but this one gives me null
Debug.Log(Container.transform.GetChild(i).Find("Fill - Top").transform.GetComponent<Image>());
what am i doing wrong?
Answer by Bunny83 · Sep 13, 2021 at 06:57 PM
Well, if GetComponent returns null there's only one possible reason for this: The object you're calling GetComponent on does not have that component.
To narrow down the issues further, lets break it down into smaller pieces. First of all, make sure the object you're dealing with is actually the right one. For this you can pass that object as second "context" parameter to a Debug.Log statement. When you do this, clicking the log message in the console will "ping" / highlight that specific object in the scene or project panel so you know exactly what object you're dealing with.
Next you should make sure you use the "correct" Image class. There are several Image classes and you could even define your own class. We don't know which one you're looking for, but it may be the one in the UnityEngine.UI namespace? Maybe you used the wrong namespace?
So if you're not sure about the Image type you're using, in VisualStudio you can simply hover over the type and it should tell you in the hint that pops up the full classname including the namespace.
Though you can also simply print the full name of the type. So try this in your code:
Transform obj = Container.transform.GetChild(i).Find("Fill - Top");
Debug.Log("Finding type: " + typeof(Image).FullName + " on object" + obj.name, obj);
This should answer both questions at once. You would see the full name of the Image class and when you click on the log message it should tell you the exact object.
I manage to get it but it seems redundant and way too elaborate. must be a simpler way. it's a long and illegible line.
Container.transform.GetChild(i).Find(elementNames[i]).gameObject.transform.GetChild(i).gameObject.GetComponent().color = allColors[i];
Why do so many people always add a .gameObject or a .transform everywhere, just in case? GetChild as well as Find both return a Transform component. So using ".transform" on a transform reference is completely pointless. The ".transform" property is just a shortcut for GetComponent<Transform>()
.
You should generally avoid such long chains because if anywhere in that chain is an error, you can't tell which part fails. Break up such long chains into seperate lines with proper temp variables. This automatically documents what the code is actually doing, since you can name those variables properly. Also if a null reference exception happens at any stage, you know the line number and exactly at which point it fails.
We don't know what type your Container variable has. If it's a Transform reference, you would not need the first ".transform" either. Anyways you can reduce your single line to
Image img = Container.transform.GetChild(i).Find(elementNames[i]).GetChild(i).GetComponent<Image>()
img.color = allColors[i];
Though as I said, it's better to break the code up into individual parts like
var child = Container.transform.GetChild(i);
var subElement = child.Find(elementNames[i]);
var elementChild = subElement.GetChild(i);
var img = elementChild.GetComponent<Image>();
However your code seems very strange. Why do you have so many sub objects? Also it seems very weird that the child index at the first level (your "i" value) matches the child index inside the nested object. This looks like a very strange setup. You should always try to avoid manually searching through code if possible. Try linking relevant objects in the inspector by exposing a Transform (or in your case an Image variable) that you can assign in the inspector. Of course that's not always possible.
Note that if there is only one Image component in a whole object sub tree, you can simply use "GetComponentInChildren" instead of GetComponent. It returns the first component it can find on the object you call this method on or any of its child objects. So often times it's not necessary to manually walk down the hierarchy. You can also use your own scripts as a kind of "marker". So you attach your script to a nested object and call GetComponentInChildren to get that nested object (given there is only one such object in the tree you're searching through).
I don't know why others do it but I do it because it's still abstract for me how it works in Unity. I'm learning.
Your answer
Follow this Question
Related Questions
how can I check if an object is null? 4 Answers
what is null 1 Answer
XMLDocument GetElementByID returning null 1 Answer
Confused as to why I'm getting a NullReference Exception 1 Answer
Destroying an object not working 1 Answer