Search Unity

[SOLVED] PrefabUtility.InstantiatePrefab not preserving prefab connection

Discussion in 'Immediate Mode GUI (IMGUI)' started by murkantilism, Mar 8, 2017.

  1. murkantilism

    murkantilism

    Joined:
    Apr 30, 2012
    Posts:
    21
    X-Post from the Scripting forums - not sure if this is a better place for this type of question:

    This simple Editor tool to instantiate Prefabs is doing so, but the instantiated objects are missing their connection to the prefab (aka not blue, updating prefab doesn't show changes in copies).

    Code (CSharp):
    1. [ExecuteInEditMode]
    2.     public class FixMazePrefabConnections : MonoBehaviour
    3.     {
    4.         foreach (GameObject maze in mazes)
    5.         {
    6.             // Instantiate blank maze
    7.             GameObject newMaze = PrefabUtility.InstantiatePrefab(blankMazePrefab) as GameObject;
    8.         }
    9.     }
    I've tried suggestions like using:

    Code (CSharp):
    1. EditorSceneManager.MarkSceneDirty(EditorSceneManager.GetActiveScene());
    and:

    Code (CSharp):
    1. Undo.RecordObject(newMaze, "");
    to no avail. Any clue what I can try to preserve the connections?
     
  2. SarfaraazAlladin

    SarfaraazAlladin

    Joined:
    Dec 20, 2013
    Posts:
    280
    Try using a generic var and then casting to a gameobject

    Code (CSharp):
    1. var clone : GameObject = PrefabUtility.InstantiatePrefab(Selection.activeObject as GameObject) as GameObject;
     
  3. murkantilism

    murkantilism

    Joined:
    Apr 30, 2012
    Posts:
    21
    Tweaked that for C#, no dice. Still no connection preserved:

    Code (CSharp):
    1. // Instantiate blank maze
    2. var newMaze = PrefabUtility.InstantiatePrefab(blankMazePrefab as GameObject) as GameObject;
    3. //GameObject newMaze = PrefabUtility.InstantiatePrefab(blankMazePrefab as GameObject) as GameObject;
    4.            
     
  4. SarfaraazAlladin

    SarfaraazAlladin

    Joined:
    Dec 20, 2013
    Posts:
    280
    Oh... is your game object array coming into this operation without null game objects? When you do GameObject object = new GameObject(); it will create the game object there and then in your scene. (As if you instantiated)
     
  5. murkantilism

    murkantilism

    Joined:
    Apr 30, 2012
    Posts:
    21
    No the List<GameObject> mazes is not null, I omitted that code. It's a list of all the "maze" gameObjects in the Scene. A lot of these mazes have lost their Prefab connection for one reason or another, so I'm trying to write an editor tool to reconnect them.

    What this loop is doing is creating a "copy" of each maze from it's original Prefab, and then copying the individual maze component parameters over (hierarchy index, dimensions, position, rotation, so on).

    At no point am I using GameObject obj = new GameObject();

    I'm using exclusively PrefabUtility to instantiate new gameObjects, which is supposed to preserve the prefab connection.
     
  6. CDF

    CDF

    Joined:
    Sep 14, 2013
    Posts:
    1,311
    You need to find the Prefab parent of your scene objects to instantiate their prefabs.

    PrefabUtility.GetPrefabParent

    then instantiate using that

    PrefabUtility.InstantiatePrefab(PrefabUtility.GetPrefabParent(blankMazePrefab))
     
    murkantilism likes this.
  7. murkantilism

    murkantilism

    Joined:
    Apr 30, 2012
    Posts:
    21
    Thank you for the suggestion, I implemented it and found that it worked successfully for instantiating a GameObject with it's prefab connection preserved. However I discovered at other parts of the script were breaking the connection.

    What I was doing: copying over all of the "previous" Scene object's parameters to the newly instantiated prefab; things like the top-level transform position/rotation/scale down to the scale of certain child objects. I am fairly certain that these operations are what broke the connection of the newly instantiated mazes.

    I discovered the PrefabUtility method ConnectGameObjectToPrefab() which solved all my problems. The updated loop is now:

    Code (CSharp):
    1.  
    2. foreach (GameObject maze in mazes)
    3. {
    4.     // Re-establish prefab connection
    5.     PrefabUtility.ConnectGameObjectToPrefab(maze, PrefabUtility.GetPrefabParent(maze) as GameObject);
    6.  
    7.     Debug.Log("Re-established prefab connection for: " + maze.name);
    8. }
    So for the purposes of this tool, instantiation is not needed it turns out.
     
    PandaArcade likes this.