Creating prefabs from models by script

Hi,

Before updating to Unity 2018.3, we used to have a custom AssetImporter for model types. Doing so, upon importing a new model in the project we could create a prefab for that model. If the prefab already existed, we replaced it.

Now, with the Nested Prefabs workflow, I am unable to use the new API.

if( !File.Exists( destinationPath ))
    return PrefabUtility.CreatePrefab(destinationPath, modelAsset);
else
    return PrefabUtility.ReplacePrefab(modelAsset, AssetDatabase.LoadAssetAtPath<GameObject>(destinationPath), ReplacePrefabOptions.ReplaceNameBased);

Now I am supposed to call SaveAsPrefabAsset instead, as far as I know, in both situations. When I do so, however, I get an ArgumentException saying “Can’t save persistent object as a Prefab asset”.

What should I do to be able to create a prefab from a model by script?

1 Like

Hi,

That does sound like a bug, could you file a bug report please.

That said I strongly recommend you explore using Prefab Variants if you want to have Prefabs based on Models.
Using Variants means that changes to your models propagate automatically and you don’t have to manually update your custom Prefabs.

If that’s indeed a bug, I will report it.

About prefab variants, it sounds great to make a prefab variant from the model, but how can I do that from code?

Variants are basically instances of other prefabs saved into their own separate prefabs.
So instantiate the model and save the instance to a new prefab.

var modelRootGO = (GameObject)AssetDatabase.LoadMainAssetAtPath("Assets/MyModel.fbx");

var instanceRoot = PrefabUtility.InstantiatePrefab(modelRootGo);
var variantRoot = PrefabUtility.SaveAsPrefabAsset(instanceRoot, "Assets/MyModel_Variant.prefab");
3 Likes

Instantiating the model, creating a prefab from the instance and then destroying the instance solved the problem.

Thank you so much!

I still sent a bug report though.

Now that ReplacePrefab w/ ReplacePrefabOptions.ReplaceNameBased is obsolete what is the alternative?

With ReplacePrefab w/ ReplacePrefabOptions.ReplaceNameBased I create Prefabs with a script (I have 100’s of prefabs with identical & complex hierarchies) and this allowed me to adjust & modify prefabs without breaking all scene instance serialized links. Now that ReplacePrefab w/ ReplacePrefabOptions.ReplaceNameBased is obsolete I am unsure what to do. I just used PrefabUtility.SaveAsPrefabAsset and it broke my scene serialized links (I lost a LOT of work!).

Edit: Looks like this will be fixed. Unity post here.

2 Likes

If this is a bug is a very unfortunate one. I have to load an fbx GameObject to extract a child object and make a prefab of it.

I can’t load it with PrefabUtility.LoadPrefabContents because is an fbx and not a normal prefab.

I can’t always create a new temporary scene for something that seems a regression of this:

and this problem is very common if you try to reimport an fbx because you probably select it when reimport it.

I can’t save directly the fbx to alter it after this because of this bug.

The only way I see to create my prefab is to instantiate it in the current scene and then remove it, but this alter the scene I’m working…

According to this thread Unity stated…

“We’re working on a replacement for ReplacePrefab. You can keep using the obsolete API in the mean time. The replacement was meant to have been done when we shipped but didn’t make it. It’s a mistake on our part that the old method was marked obsolete without the replacement being ready. Sorry for the inconvenience.”

Yep, I know, but even with ReplacePrefab I got the error “Can’t save persistent object as a Prefab asset”, so that doesn’t change a lot.

Hello everyone, I am trying to save a gameobject as a prefab in edit mode, but the prefab is being saved with its MeshFilter but not the actual mesh. Is there a way I can save the prefab and keep the reference to the mesh?

1 Like