Adding a child GameObject to a Prefab. HOW ?

Hello there everyone.

After a day and a half fighting Prefabs, I’m raising the white flag and asking for help. I have a prefab, it’s a gameplay element that’s placed over inumerous scenes in the project. Usually the changes I need to do consist in adding a Component, changing a value in a Script , and so on, all these changes work perfectly. I change the prefab , all the instances in the different scenes update.

Awesome :sunglasses:
Until now…!

I need to make a change to a prefab which consists in adding a new GameObject to it’s hierarchy . Everytime I do so, Unity interprets it as a new prefab, and screws it all up, resetting the transform, making all the instances in the different scenes, go out of place, on top of each other. Is there any way to do this properly ? I am doing this because of the ParticleSystem.Update() problem , so it would really suck that the solution I have leads me to another problem. Any ideas ?

Thanks in advance!

So, in game while game is running, you add an object into the prefabs hierarchy, but the prefab is resetting its values??

Wierd. I would not expect that.

If I am misreading you…

NewObject.transform.parent = prefab.transform;

Is how you hand an object to another’s hierarchy.

1 Like

No , not in run time. I mean I want to add it to the prefab , so all the instances update too. Adding it in real time would beat the purpose of what I’m trying to do, I am trying to add it to the Source Prefab.

Pull the prefab into the scene, add any desired game object to the hierarchy and hit apply in the upper right corner.

Yes to add objects to a prefab, do it via the editor, scene window, then just pull it back into the Project panel when done.

Is there a better answer to this question? I have a very large number of prefabs I need to add child objects to and doing them one by one seems quite an ominous prospect.

You can’t parent a new GameObject directly to a prefab for ‘safety’ (read: idiot-proofing) reasons.

However, what you can do is have an editor script that pulls a prefab into the scene, adds a GameObject to it the way you want, and then applies the changes automatically.

Thanks, it’s what I figured. I think Unity is missing some simple features when it comes to Prefabs, like bulk apply, and I can’t seem to drag many prefabs to my scene at once. I’ll have a go at writing the script for this anyway, cheers again.

For anyone interested here is a short script that suited my needs, so hopefully you can adapt it. You have to define the name of a source object and the gameobject children you want to copy. Then just select the prefabs you want to copy them to and choose the menu item.

edit: a few tweaks for my own sanity

[MenuItem (“Custom/Copy Objects to Prefab”)]
static void AddObjectsToPrefab ()
{
// Define the source
string sourceName = “sourceObject”;
GameObject sourceGO = GameObject.Find(sourceName);

// Some checks to try to ensure we don’t use this method by mistake
if ( Selection.activeGameObject.activeInHierarchy )
{
Debug.Log(“Selection is within scene heirarchy. This function is only for Prefabs.”);
return;
}

if ( sourceGO == null )
{
Debug.Log(String.Format(“No object named {0} found in the current scene”, sourceName ) );
return;
}

if ( !EditorUtility.DisplayDialog(“Confirm copy”, “Confirm you wish to copy objects from " + sourceName +
" to " + Selection.gameObjects.Length + " prefabs.”, “Yes”, “No”)
)
{
Debug.Log (“Cancelled”);
return;
}

// Define list of objects to copy from the source
string[ ] goList = new string[ ]
{
//“exclamation”,
//“question”,
“Mind”,
“Obstacle Avoidance Collider”,
“Path Manager”,
“Sensor”
};

List sourceObjects = new List();

// get list of desired components from the source
foreach (Transform child in sourceGO.transform)
{
for (int i=0; i < goList.Length; i++ )
{
if ( child.gameObject.name.Equals(goList*) )*

  • {*

  • sourceObjects.Add ( child.gameObject );*

  • }*

  • }*

  • }*

  • foreach( GameObject prefab in Selection.gameObjects )*

  • {*

  • // create an instance of the prefab*

  • GameObject prefabInstance = PrefabUtility.InstantiatePrefab( prefab ) as GameObject;*

  • // clone the source objects and add to the prefab*

  • foreach ( GameObject sourceObject in sourceObjects )*

  • {*

  • GameObject clone = Instantiate( sourceObject ) as GameObject; *

  • clone.transform.parent = prefabInstance.transform;*

  • clone.name = sourceObject.name; // gets rid of (clone) from the name*

  • clone.transform.localPosition = sourceObject.transform.localPosition; *

  • }*

  • // apply the instance to the prefab*

  • PrefabUtility.ReplacePrefab(prefabInstance, PrefabUtility.GetPrefabParent(prefabInstance), ReplacePrefabOptions.ConnectToPrefab); *

  • // remove the instance from the scene*

  • DestroyImmediate( prefabInstance );*

  • }*

  • }*

1 Like

Thanks, that’s what I was looking for!

i’m searching for ways to set a prefab under another object’s hierarchy, simply happy to find it here.

so setting hierarchy is done via transform, is that right?

If you want to add a gameObject (which is currently inside the hierarchy) to a prefab as its (prefab’s) child then you need to drag the prefab into the scene (which will also appear in the hierarchy) and then drag that gameObject into the prefab(which is inside the scene/hierarchy) ie. make a child. Then drag the prefab (which is inside the scene/hierarchy) back on the main prefab(inside the project). Now you’re free to delete the prefab which is inside the scene/hierarchy.

In this manner, you can also edit anything about prefab by dragging it to the scene, edit it accordingly and then drag it back on the main prefab (inside project).

Hope you were looking for this and it helped.

Hey, I just recently wrote a utility to do this exact thing from script really easily. Just checkout and download my script from github. https://github.com/GameBrainDev/AddGameobjectfromscriptPrefabAsset

According to this article you have to apply changes after adding the objects as children to prefab instance. But there is no answer how to correctly set prefab instance transform as child parent. Simple .SetParent() leads to error:Setting the parent of a transform which resides in a Prefab Asset is disabled to prevent data corruption (GameObject: ‘sp’).

Probably, someone need this solution:

private void AddSpawnPoint()
        {
            var spawnPoint = new GameObject("sp");
            using var editingScope = new PrefabUtility.EditPrefabContentsScope(AssetDatabase.GetAssetPath(_spawnPointsLayout.gameObject));
            spawnPoint.transform.SetParent(editingScope.prefabContentsRoot.transform);
            spawnPoint.transform.localPosition = Vector3.zero;
            spawnPoint.transform.rotation = Quaternion.identity;
            spawnPoint.AddComponent<SpawnPoint>();
        }
6 Likes

I have some problems with that script. It seems that when I try to add the child I get this error

Setting the parent of a transform which resides in a Prefab Asset is disabled to prevent data corruption (GameObject: 'lockImage').

You’re my hero! This works like a charm. Thanks for putting this out here.