- Home /
Access components in children of a prefab?
I have prefabs with a component say, "ClassA". These prefabs have multiple children with the component "ClassB". ClassB is used to store configuration properties that define the ClassA prefab. So the idea is that I can search through all of my Class A prefabs and check the properties on its children so I can determine which prefab I need. The reason I have used children to store these properties is because I wanted to use editor gizmos to make it easier to config each prefab (there are 27 children per prefab which would make it confusing to name & edit as standard public properties on the prefab).
The problem I'm having is that myPrefab.GetComponentsInChildren<ClassB>()
is returning null, which really spoils my day. I don't want to have to instantiate all of my prefabs just to pick which one I need. Why is it that I can access properties on the prefab (ClassA) but not its children? Is there a way to achieve this without simply having all of my properties in ClassA?
Thanks in advance.
edit for clarity:
myPrefab - ClassA <-- I can access the component on the prefab just fine
+ child - ClassB <-- but I can't access the components in the prefab's children at all
+ child - ClassB
...
+ child - ClassB
Burnzoire, did you get an answer to this question? Your issue matches $$anonymous$$e very closely. Can you provide some insight to how you solved this? I am attempting to use an editor script to modify my prefabs and prefab children at edit time. but this does not seem possible without instantiating them, making the change, saving back the prefab, and finally deleting the instantiated version. even this is not working very well. Any help will make you a hero - in my $$anonymous$$d.
Hey there,
i am having the exact problem. I need to access the hierachry of an non-instantiated prefab. Is there any chance to access the children?
Answer by Bunny83 · Jul 10, 2012 at 06:08 PM
GetComponentsInChildren has that already mentiond restriction to return only active gameobjects / components. Just iterate manually through them. Something like that:
private static void ProcessChild<T>(Transform aObj, ref List<T> aList) where T : Component
{
T c = aObj.GetComponent<T>();
if (c != null)
aList.Add(c);
foreach(Transform child in aObj)
ProcessChild<T>(child,ref aList);
}
public static T[] GetAllChilds<T>(Transform aObj) where T : Component
{
List<T> result = new List<T>();
ProcessChild<T>(aObj, ref result);
return result.ToArray();
}
You can of course implement it as extension methods to easily access them:
public static T[] GetAllChilds<T>(this Transform aObj) where T : Component
{
List<T> result = new List<T>();
ProcessChild<T>(aObj, ref result);
return result.ToArray();
}
public static T[] GetAllChilds<T>(this GameObject aObj) where T : Component
{
List<T> result = new List<T>();
ProcessChild<T>(aObj.transform, ref result);
return result.ToArray();
}
I know this is an older post but, In my search for answer to a very similar problem as posted here I almost did not read this anwser after reading the first 2. But this is exactly what i was looking for. And hopefully others can find it too. thanks
Answer by MasterLu · Aug 18, 2014 at 07:44 PM
I had the same Problem. Searching components from childObjects in a prefab via editorWindow returns null. My solution was using GetComponentsInChildren(true)
to include nonActive childObjects.
Answer by DaveA · Mar 31, 2011 at 11:39 PM
PrefabA contains a script ClassA, and PrefabB contains a script ClassB, then you add PrefabB's to PrefabA (and make sure A stays a prefab), is that basically what you did? If so, the problem may be that you can't 'nest' prefabs and have them retain their lower-level individuality.
Other than that, maybe you can post some code and/or screenshot for us to review.
No, ClassB is not a prefab. They are just components on the prefab's children.
To be more specific, each prefab is a building block that contains multiple children with Tag components. These tag components are used as meta data to deter$$anonymous$$e which blocks connect to each other.
I'll post code when I'm at my computer later, but I was hoping the question was a bit simpler to explain! Simply put, 'myPrefab.getComponentsInChildren' doesn't appear tp work on an uninstantiated prefab. It seems that ONLY the components on the upper-most level of the prefab are accessible in an uninstantiated state?
Ah ok. Being children, maybe they do need to be instantiated unless there's a way to 'dig into' the prefab itself, rather than an instantiation of it. You might instantiate one and make it inactive just to have around.
Yeah it's for a real-time editor component of my game. So having every piece instantiated isn't ideal but I guess if they're inactive it might be acceptable.
It's actually fairly normal to have instantiated prefabs in your scene due to editor scripts (i.e. it's one way to do previews of 3D meshes via a Camera with a render texture target).
This is what gameObject.hideFlags is for. http://docs.unity3d.com/ScriptReference/HideFlags.html . Hope this gives you ideas! (It gave me ideas when I found out it was kosher!)
Answer by Adam-Mechtley · Jul 10, 2012 at 05:25 PM
As far as I can tell, this is not possible.
The reason is because, as noted in the documentation, GetComponentsInChildren only returns components on active objects. Un-instantiated prefabs (i.e., assets in your asset database) are all deactivated (and must be—you get an error message saying that Unity will crash if you try to create an asset using an active GameObject). As such, it seems you must instantiate your prefab in a new scene to extract any needed data from children, or to make any necessary modifications to the source asset.
Answer by stevesan · Nov 25, 2013 at 05:14 PM
I'm having this issue too. My solution is to simply descend the hierarchy depth-first and call GetComponent on each child, looking for what I need. I guess GetComponent and GetComponentsInChildren behave differently unfortunately.