Search Unity

Apply multiple added GameObjects to a prefab

Discussion in 'Prefabs' started by TacticalShader, Apr 15, 2020.

  1. TacticalShader

    TacticalShader

    Joined:
    Dec 5, 2018
    Posts:
    27
    In a editor, I'm creating multiple gameobjects and I need to apply them directly to the prefab. So basically what I did is :

    Code (CSharp):
    1. GameObject prefab = GetPrefab();
    2. string prefabPath = PrefabUtility.GetPrefabAssetPathOfNearestInstanceRoot(prefab);
    3.  
    4. for (int i = 0; i < 10; i++)
    5. {
    6.      GameObject instance = new GameObject();
    7.      ....
    8.      PrefabUtility.ApplyAddedGameObject(instance, prefabPath, InteractionMode.AutomatedAction);
    9. }
    Problem is, each ApplyAddedGameObject() is very slow : the full process is taking minutes of loading at this point.

    So I'm looking for a function to apply gameobjects in bulk, but it doesn't seem to exist publicly in the API (please correct me if I'm wrong !).

    In the Unity CS reference github, I found the following function, called internally by ApplyAddedGameObject() like this :
    PrefabUtility.AddGameObjectsToPrefabAndConnect(
    new GameObject[] { gameObject },
    prefabSourceGameObjectParent);

    Could we have something like this in the API ?

    Thank you for your time.
     
  2. SteenLund

    SteenLund

    Unity Technologies

    Joined:
    Jan 20, 2011
    Posts:
    639
    Hi,

    While a batch API would be nice I think it would be better to edit the prefab directly in this case
    Code (CSharp):
    1. GameObject prefab = GetPrefab();
    2. string prefabPath = PrefabUtility.GetPrefabAssetPathOfNearestInstanceRoot(prefab);
    3.  
    4. // The editing scope will automatically save, reimport prefab and unload contents
    5. using (var editingScope = new PrefabUtility.EditPrefabContentsScope(prefabPath))
    6. {
    7.     var rootTransform = editingScope.prefabContentsRoot.GetComponent<Transform>();
    8.     for (int i = 0; i < 10; ++i)
    9.     {
    10.         var newGo = new GameObject();
    11.         newGo.GetComponent<Transform>().parent = rootTransform;
    12.     }
    13. }
    14.  
     
    TacticalShader likes this.
  3. runevision

    runevision

    Joined:
    Nov 28, 2007
    Posts:
    1,892
    TacticalShader likes this.
  4. TacticalShader

    TacticalShader

    Joined:
    Dec 5, 2018
    Posts:
    27
    Hey thank you guys, for the quick replies !

    Interesting ! Unfortunately, we are stuck in Unity 2019.3 for what-it-seems the rest of the production of our game and this function is only available in Unity 2020.1 (unless it will be backported to 2019.4), but I will keep that in mind !

    It works ! The process now only takes a few seconds. Thanks ! :)
     
  5. SteenLund

    SteenLund

    Unity Technologies

    Joined:
    Jan 20, 2011
    Posts:
    639
    @TacticalShader

    It is just a simple wrapper around
    PrefabUtility.LoadPrefabContents
    that you can easily implement in your project. It looks like this
    Code (CSharp):
    1.         public struct EditPrefabContentsScope : IDisposable
    2.         {
    3.             public readonly string assetPath;
    4.             public readonly GameObject prefabContentsRoot;
    5.  
    6.             public EditPrefabContentsScope(string assetPath)
    7.             {
    8.                 this.assetPath = assetPath;
    9.                 prefabContentsRoot = PrefabUtility.LoadPrefabContents(assetPath);
    10.             }
    11.  
    12.             public void Dispose()
    13.             {
    14.                 PrefabUtility.SaveAsPrefabAsset(prefabContentsRoot, assetPath);
    15.                 PrefabUtility.UnloadPrefabContents(prefabContentsRoot);
    16.             }
    17.         }
    Makes editing prefabs directly a little easier. We implemented this with permission from someone who posted it in this forum.

    But I am glad the other solution also worked.
     
    TacticalShader likes this.