All references to prefab lost after using PrefabUtility.SaveAsPrefabAsset(...) due to new FileId

I’m trying to manipulate a prefab via script in ways not supported by the new prefab system (like destroying a child, or reordering children). Before 2018.3, this could be achieved like this:

var instance =(GameObject)PrefabUtility.InstantiatePrefab(SomePrefab);
PrefabUtility.DisconnectPrefabInstance(instance);
//Manipulations here
PrefabUtility.ReplacePrefab(instance, SomePrefab);
DestroyImmediate(instance);

With the new system, the closest I could get to was this:

var instance =(GameObject)PrefabUtility.InstantiatePrefab(SomePrefab);
PrefabUtility.UnpackPrefabInstance(instance , PrefabUnpackMode.Completely, InteractionMode.AutomatedAction);
//Manipulations here
PrefabUtility.SaveAsPrefabAsset(instance , AssetDatabase.GetAssetPath(SomePrefab));
DestroyImmediate(instance );

However, with this new method the prefab file is assigned a new FileId and all references to it in scenes or other prefabs are lost. Using the deprecated ReplacePrefab instead of SaveAsPrefabAsset yields the exact same results. I have found that without unpacking the prefab all references stay intact after saving, but I need to unpack or else the manipulations will throw errors.

Is this intended behavior? Or is there another way I can achieve this that I’ve missed? Thanks in advance.

I missed ReplacePrefabOptions.ReplaceNameBased, using that it works as I want it to. This can be closed.

Yes this is intended behaviour, though we are considering improving it.

The correct way for you would be to use PrefabUtility.LoadContents.

var path = AssetDatabase.GetAssetPath(SomePrefab);
var contentRoot = PrefabUtility.LoadPrefabContents(path);
//Manipulations here
PrefabUtility.SaveAsPrefabAsset(contentRoot , path);
PrefabUtility.UnloadPrefabContents(contentRoot);
1 Like

Thanks, I’ll check that out!

Hello SteenLund

Now I’m using the new prefab system. When I use PrefabUtility.SaveAsPrefabAsset api to replace a prefab by a new Instantiate gameObject, all references to the prefab also lost.
Before I use PrefabUtility.ReplacePrefab to do it, and use ReplacePrefabOptions.ReplaceNameBased, it works fine, but now it does not work.
How can I to do it?

I am still having problems restoring my workflow with this new prefab system.

What I had working before was to make some manual modifications to a prefab instance, and then perform an automated set of actions that would further modify the prefab instance and then apply the changes to the root prefab. All references to the root prefab remained intact.

Like the OP, I’ve found that calling UnpackPrefabInstance and SaveAsPrefabAsset breaks all references to the previous prefab asset. Unfortunately, calling LoadPrefabContents rather than UnpackPrefabInstance doesn’t really make any sense for my use case, since I want to do further automated processing to changes I’ve already made manually to a prefab instance. Calling LoadPrefabContents returns a gameobject with none of the changes I’ve made already that I need to keep.

Any ideas on how to fix?

Sorry for necro, just ran into this issue and it’s completely messing with the dev flow. Any solutions?