I am developing an edit-time level editor.
I have an Apple prefab. I also have an AppleTree prefab. The AppleTree prefab has, as children, several Apple prefab instances.
Both prefabs have an attached script, called 'Prop'
I drag an AppleTree prefab into my scene. I drag an apple into my scene.
I now have Editor Code that will serialise information from these objects (essentially, their positions, and the name of the prefab from which they were instantiated.)
Other editor code reads that serialised data, and instantiated game objects from the prefabs, using the prefab name saved in the serialised data.
When the 'save' code runs, it uses
var scripts= GameObject.FindObjectsOfType<Prop>();
which returns every instance of that script.
This correctly returns the script on the instance of the AppleTree, and the instance of the Apple, that I dragged into the scene.
Which is fine.
But it also returns all of the Prop scripts that are on Apple Game Objects that are children of the AppleTree - which I don't want, as, when I instantiate an instance of AppleTree, Unity will instantiate all of those apples for me.
I am looking for a generic method to filter out those particular apples.
The only working solution I have is to walk up the hierarchy from the GameObject of every Prop script, checking if that, too, has a Prop script, until I reach the highest level with a Prop script, and serialise that.
Even this isn't perfect, because, if I were to foolishly drag an extra apple as a child of my AppleTree, then that extra apple would not get serialised.
I don't believe there is any way to tell if an object was instantiated 'directly' from a prefab - so I need to find an alternate solution....
Unless you're already using it for something else you could use GameObject.FindGameObjectsWithTag as the defining criteria instead. Your prefab objects could be given a "serializeThis" tag and you could then go into the AppleTree prefab and manually override the tags of the internal Apples.
Extra Apples added to the AppleTree prefab would be detected correctly and the only time where you would have to pay attention is at the inception of the prefab.
GameObject[] objs = GameObject.FindGameObjectsWithTag("serializeThis");
Prop scripts[] = new Prop[objs.Length];
for(int i=0; i<objs.Length; i++){
scripts[i] = objs[i].GetComponent<Prop>();
}