- Home /
Accessing instantiated GOs nested in prefabs with GetComponent
I asked this on the forums too in a multi-question post but haven't gotten answer to this yet. So I figured someone else might need this information too and add it to unityAnswers.
So the question, how do I access prefabs that are created with Instantiate and have nested GameObjects.
I'm instantiating the object on runtime with
var house1:GameObject = Instantiate(Resources.Load("HouseGreenSmall"), Vector3(5,-0.15,7), Quaternion.Euler(0,180,0));
I'm not entirely sure if they even are GOs or prefabs. You can see the object in the project view, hierachy view and the script doorlink attached to DoorTrigger GO (or prefab?). I've renamed the Door Trigger to DoorTrigger to avoid any confusion with the space, the screenshot is just from the old version.
I've tried several syntaxes but everything produces some error.
(by the way the accessthis() function is just for debugging)
house1.GetComponent(doorlink).accessthis();
produces NullReferenceError
print(house1.transform.position.x);
works, it prints the correct coordinate, but the coordinate of the GreenHouseSmall prefab.
print(house1.anything.transform.position.x);
produces " 'Anything' is not a member of 'UnityEngine.GameObject "
Wow this question is pretty messed up. Sorry for the inconvenience :|
Answer by Jaap Kreijkamp · Jan 15, 2010 at 02:04 AM
Don't follow your story exactly but I believe you want to find a child of a GameObject/Transform.
The easiest way to do it is through the Transform.Find
method. So say you have a GameObject named House with a child GameObject named Door. In the script attached to House:
...
var doorTransform : Transform = transform.Find("Door");
var doorGO : GameObject = doorTransform.gameObject;
...
You could consider making doorTransform and/or doorGO global variables and setting their values in the Awake function for performance reasons if you need to access the values often. This would result in:
private var doorTransform : Transform; private var doorGO : GameObject;
function Awake() { doorTransform = transform.Find("Door"); doorGO = doorTransform.gameObject;
}
now you can just use doorTransform and doorGO in your functions.
I'm terribly sorry but I didn't remember to tell the vital part that I'm instantiating the whole thing on runtime. See the third paragraph, just added it. The thing I'm asking is to run the accessthis function in the doorlink script.
I have a similar problem, trying to reference nested GameObjects. However, the suggestion transform.Find("oneBone") does not work. Nor does transform.Find("/oneBone"), which the docs suggest a slash will cause Find to traverse the hierarchy. Any further answers?
Answer by Lucas Meijer 1 · Jan 15, 2010 at 02:05 AM
in javascript,
house.GetComponent(DoorLink).accesthis()
should work. Please note that "DoorLink" and "acccesthis" are case sensitive.
PS Prefabs are gameobjects. The only difference between a gameobject in your scene, and a prefab is that one is saved in the scenefile, and the other is saved into a .prefab file in your Assets folder.
Actually that produces NullReferenceException, just as house1.GetComponent(doorlink).accessthis(); If you see the screenshot the script is called doorlink, not DoorLink. I'm not sure if that matters. And see the edit I made, also explained it in the comments of above answer. This question turned out really bad, I'm terribly sorry.
Have you checked if the house variable has a value, what Lucas suggested should work, but indeed DoorLink must match the name of the javafile exactly (case sensitive), so in your case it would be 'doorlink'. Try with a debug statement to see if house has indeed a value.
Answer by Ryuuguu · Jan 15, 2010 at 02:58 AM
In the screen shot, doorTrigger is a child game object of houseGreenSmall and doorlink is a componet of doorTrigger.
so stealing some code from Jaap Kreijkamp's and Lucas Meijer's answers
var doorTransform : Transform = transform.Find("DoorTrigger");
doorTransform.GetComponent(DoorLink).accesthis()
This sounds promising. Still, I'd like to be able to "spawn" many clones of the house with js and the doors to lead to different levels, so I'd like to be able to do something like house1.GetComponent(DoorTrigger.GetComponent(doorlink).accessthis()) Do I make any sense?
Your code house1.GetComponent(DoorTrigger.GetComponent(doorlink).accessthis()) can be broken down to x =DoorTrigger.GetComponent(doorlink).accessthis(); house1.GetComponent(x); where is a type. what you want is house1.transform.Find("DoorTrigger").GetComponent(doorlink).accessthis(); or if you have only one DoorLink component under house1 house1.GetComponentInChildren(DoorLink).accessthis(); if you have more than one DoorLink it gets the first in depth first search.
Answer by Cyclops · Feb 05, 2010 at 05:02 PM
Jaap's first answer does work. I had to experiment with it a bit, though, as Find doesn't work quite as I expected. Apparently it only finds direct children GameObjects, and not, say, grandchildren. :)
I had an imported model asset called anArm, which had nested GameObjects as anArm/skeleton/oneBone/twoBone.
GameObject tmpArm = (GameObject)Instantiate(anArm, thePos, Quaternion.identity);
Given that reference, I first tried this code:
Transform lastBone = tmpArm.transform.Find("twoBone");
It didn't work, either with or without a slash "/twoBone". However, when I included the complete child list:
Transform lastBone = tmpArm.transform.Find("skeleton/oneBone/twoBone");
it worked correctly, and I was able to access the last GameObject. Granted, in the OP, your screenshot doesn't show nesting of more than one level, so the Find should have worked for you. Did it solve your problem?
John C>
"For all your days, prepare, and meet them ever alike;
When you are the anvil, bear - when the hammer, strike."
Your answer
Follow this Question
Related Questions
Only change a variable on the instaniated object not the prefab. 0 Answers
Limiting respawns on scene 1 Answer
Get unity to recognize prefab in C# 2 Answers
Reference an Instance of an Object?C# 1 Answer
GetComponent vs AddComponent 3 Answers