- Home /
Cannot GetComponentInChild of a Prefab
I am trying to create a UI panel with a Text object as its child into a prefab. Every time the function is called it's supposed to produce this prefab. I am getting this error:
NullReferenceException: Object reference not set to an instance of an object
The function looks like this:
private void CreateLines() {
foreach (var line in lines) {
message = new GameObject("New Message");
message.transform.SetParent(content, false);
messageText = message.GetComponentInChildren<Text>(true);
messageText.text = line.text;
}
}
In my searching, it looks like this is not possible currently. If this is the case, what is a good work around?
Answer by Bunny83 · May 30, 2019 at 12:07 AM
You mixed up terms that don't belong here. You don't have any prefabs involved here. All you do is creating a new empty gameobject each for loop iteration. Of course a new empty gameobject doesn't have any components except the Tranform component.
GetComponent / GetComponentInChildren will search for an existing component on the given object and return the reference to it if one was found. As i said an empty gameobject doesn't have any components, so obviously GetComponentInChildren will return null. There's also no point in using GetComponentInChildren over GetComponent in this case since a new gameobject doesn't have any children and you don't attach any.
It's not really clear what you want to do. I see two possible scenarios:
You actually created a prefab in the project that should represent a message. This prefab may have a Text component on a child object. If that's the case you don't want to use
new GameObject
but instead usemessage = Instantiate(yourPrefabReference);
to create an instance of your prefab.If you don't have a prefab setup in your project and you actually want to create the object on the fly procedurally, you should use
message .AddComponent<Text>()
to add a new Text component to your message object. Though keep in mind that you have to initialize everything manually
In many cases it's easier to setup a prefab in the editor and instantiate it at runtime.
You actually created a prefab in the project that should represent a message. This prefab may have a Text component on a child object. If that's the case you don't want to use new GameObject but ins$$anonymous$$d use message = Instantiate(yourPrefabReference); to create an instance of your prefab.
Thank you, this works now.
private void CreateLines() {
foreach (var line in lines) {
message = Instantiate(message);
message.transform.SetParent(content, false);
messageText = message.GetComponent<Text>();
messageText.text = line.text;
}
}
Note that if "message" is your prefab reference you shouldn't replace it with an instance of the prefab. The second call of Instantiate would clone not the prefab but the object already in the scene. This may not be an issue in your case but can cause several issues in the long run. So if message is your prefab reference, you should do something like this:
foreach (var line in lines) {
var tmp$$anonymous$$sg = Instantiate(message);
tmp$$anonymous$$sg.transform.SetParent(content, false);
var msgText = tmp$$anonymous$$sg.GetComponent<Text>();
msgText.text = line.text;
}
As a general rule: Don't use member variables as temporary variables. Local variables are faster to access and cause less trouble with the outer scope.
If you have trouble to distinguish object instances from your prefabs it might be a good idea to rename your "message" variable into "messagePrefab".
Your answer
