Search Unity

Question Applying changes to a nested prefab (workflow - level design)

Discussion in 'Prefabs' started by havchr, Jan 26, 2021.

  1. havchr

    havchr

    Joined:
    Jun 18, 2009
    Posts:
    75
    Hi.
    We have a game where we are using nested prefabs in a specific way.
    The game is an "endless runner" type of game, and we are creating some zones that the level consists of and within these zones, we have patterns which contain our obstacles for the player etc.

    To iterate effectively, we like to store them like this :
    Zones(Release Candidate)
    zone 1
    z1_pattern (1)
    Some obstacle-prefab
    z1_pattern (2)
    bunch of obstacle preabs

    and if someone needs to tweak a pattern i.e objects that are children of pattern (2) - we almost always want to apply any changes from pattern (2) and children as overrides to pattern(2) - but since they are in a nested prefab, this workflow becomes very cumbersome because we must go to the Zones(Release Candidate) object, and pick every single change to apply it to pattern(2).

    Is there a way, editor script or otherwise that can apply all changes as if pattern(2) was the top level prefab?


    Maybe a picture makes it clearer :
    I want to do this for every thing on the pattern level..
    Ideally an object would have
    "Apply all changes in my hierarchy as overloads to me".
    And I could just press that button on the LA_Z1_Pattern(1) gameobject..
     
    Last edited: Jan 26, 2021
    NeatWolf likes this.
  2. havchr

    havchr

    Joined:
    Jun 18, 2009
    Posts:
    75
  3. havchr

    havchr

    Joined:
    Jun 18, 2009
    Posts:
    75
    Code (CSharp):
    1. public static class PrefabExtensions
    2. {
    3.    
    4.     public static void ApplyAllChangesInMyHierarchyToMeAsPrefab(GameObject prefabGameObject)
    5.     {
    6.         var status = PrefabUtility.GetPrefabInstanceStatus(prefabGameObject);
    7.         if (status != PrefabInstanceStatus.NotAPrefab && status != PrefabInstanceStatus.MissingAsset)
    8.         {
    9.             var origFab = PrefabUtility.GetCorrespondingObjectFromOriginalSource(prefabGameObject);
    10.             if (origFab != null)
    11.             {
    12.                 var assetPath = AssetDatabase.GetAssetPath(origFab);
    13.                 ApplyAllPrefabChangesInGivenHierarchyToPrefabAtPath(assetPath,prefabGameObject);
    14.             }
    15.         }
    16.     }
    17.    
    18.     private static void ApplyAllPrefabChangesInGivenHierarchyToPrefabAtPath(string assetPath, GameObject hierarchy)
    19.     {
    20.         var status = PrefabUtility.GetPrefabInstanceStatus(hierarchy);
    21.         if (status != PrefabInstanceStatus.NotAPrefab)
    22.         {
    23.             foreach (var ob in PrefabUtility.GetAddedComponents(hierarchy.gameObject))
    24.             {
    25.                 ob.Apply(assetPath);
    26.             }
    27.             foreach (var ob in PrefabUtility.GetObjectOverrides(hierarchy.gameObject))
    28.             {
    29.                 ob.Apply(assetPath);
    30.             }
    31.             foreach (var ob in PrefabUtility.GetAddedGameObjects(hierarchy.gameObject))
    32.             {
    33.                 ob.Apply(assetPath);
    34.             }
    35.             foreach (var ob in PrefabUtility.GetRemovedComponents(hierarchy.gameObject))
    36.             {
    37.                 ob.Apply(assetPath);
    38.             }
    39.         }
    40.         for (int i = 0; i < hierarchy.transform.childCount; i++)
    41.         {
    42.            ApplyAllPrefabChangesInGivenHierarchyToPrefabAtPath(assetPath,hierarchy.transform.GetChild(i).gameObject);
    43.         }
    44.     }
    45. }
    This ... seems to work. Maybe there is some gotchas when I do more thorough testing...
     
    sregnault likes this.
  4. SteenLund

    SteenLund

    Unity Technologies

    Joined:
    Jan 20, 2011
    Posts:
    639