Search Unity

Adding a child GameObject to a Prefab. HOW ?

Discussion in 'Editor & General Support' started by SpaceChicks, Nov 22, 2012.

  1. SpaceChicks

    SpaceChicks

    Joined:
    Oct 9, 2012
    Posts:
    22
    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 :cool:
    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!
     
  2. renman3000

    renman3000

    Joined:
    Nov 7, 2011
    Posts:
    6,697
    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.
     
    beneon likes this.
  3. SpaceChicks

    SpaceChicks

    Joined:
    Oct 9, 2012
    Posts:
    22
    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.
     
  4. Glockenbeat

    Glockenbeat

    Joined:
    Apr 24, 2012
    Posts:
    670
    Pull the prefab into the scene, add any desired game object to the hierarchy and hit apply in the upper right corner.
     
  5. renman3000

    renman3000

    Joined:
    Nov 7, 2011
    Posts:
    6,697
    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.
     
  6. GeneralMidi

    GeneralMidi

    Joined:
    Apr 6, 2013
    Posts:
    5
    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.
     
  7. superpig

    superpig

    Drink more water! Unity Technologies

    Joined:
    Jan 16, 2011
    Posts:
    4,659
    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.
     
  8. GeneralMidi

    GeneralMidi

    Joined:
    Apr 6, 2013
    Posts:
    5
    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.
     
  9. GeneralMidi

    GeneralMidi

    Joined:
    Apr 6, 2013
    Posts:
    5
    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<GameObject> sourceObjects = new List<GameObject>();

    // 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 );
    }

    }
     
    Last edited: Jul 28, 2013
    ramand likes this.
  10. iKonrad

    iKonrad

    Joined:
    Jun 23, 2013
    Posts:
    179
    Thanks, that's what I was looking for!
     
  11. beneon

    beneon

    Joined:
    Oct 20, 2013
    Posts:
    1
    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?
     
  12. yugalkishore

    yugalkishore

    Joined:
    Nov 10, 2020
    Posts:
    1
    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.
     
  13. BG_Grill

    BG_Grill

    Joined:
    Apr 18, 2020
    Posts:
    3
  14. unity_F9EDA3A11A07252C50C7

    unity_F9EDA3A11A07252C50C7

    Joined:
    Sep 16, 2021
    Posts:
    1
    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:
    Code (CSharp):
    1. private void AddSpawnPoint()
    2.         {
    3.             var spawnPoint = new GameObject("sp");
    4.             using var editingScope = new PrefabUtility.EditPrefabContentsScope(AssetDatabase.GetAssetPath(_spawnPointsLayout.gameObject));
    5.             spawnPoint.transform.SetParent(editingScope.prefabContentsRoot.transform);
    6.             spawnPoint.transform.localPosition = Vector3.zero;
    7.             spawnPoint.transform.rotation = Quaternion.identity;
    8.             spawnPoint.AddComponent<SpawnPoint>();
    9.         }
     
  15. DarkSealer

    DarkSealer

    Joined:
    Nov 24, 2015
    Posts:
    10
    I have some problems with that script. It seems that when I try to add the child I get this error

    Code (CSharp):
    1. Setting the parent of a transform which resides in a Prefab Asset is disabled to prevent data corruption (GameObject: 'lockImage').
     
  16. david-wtf

    david-wtf

    Joined:
    Sep 30, 2021
    Posts:
    25
    You're my hero! This works like a charm. Thanks for putting this out here.