Programmatically saving a prefab to disk

I would like to programmatically save a prefab to disk. I create the prefab using a method found here.

[MenuItem ("My Project/Create Simple Prefab")]
static void DoCreateSimplePrefab()
{
        Transform[] transforms = Selection.transforms;
        foreach (Transform t in transforms) {
                Object prefab = EditorUtility.CreateEmptyPrefab("Assets/Temporary/"+t.gameObject.name+".prefab");
                EditorUtility.ReplacePrefab(t.gameObject, prefab, ReplacePrefabOptions.ConnectToPrefab);
        }
}

My problem is that the prefab doesn't get saved to disk unless I manually click File/Save Project.

I tried using the following API functions but none of them worked:

Anyone have some ideas on how this could be done?

In case it helps someone else out there, I’ve had similar trouble for the longest time of losing changes to prefabs when Unity crashes even though I’ve created them and applied changes. If you don’t use ‘File > Save Project’ regularly, all work is lost. I’ve wanted a way to auto-save prefabs when applying changes for a long time now.

This is also a problem with using version control. For instance, if you make changes, then go to check them in using Git, Perforce, etc. without using ‘File > Save Project’, your changes will only be in Unity’s memory and not saved to disk and therefore are not included in your VC commit. Later, you may be surprised to find that you still have changes to check in or worse, you have conflicts with someone else who has made changes to those files. In fact, if you commit newly created prefabs without saving the project, it will exist on the hard drive in a bad state that cannot be loaded by Unity. This could break builds for other developers.

After some trial and error, I created this editor script that will auto-save after using the ‘Apply’ button as you would expect:

Assets/Editor/PrefabSaver.cs:

using System;
using UnityEditor;
using UnityEngine;

[InitializeOnLoad]
public static class PrefabSaver
{
    private static bool _waiting;
    private static DateTime _lastTime;

    static PrefabSaver()
    {
        PrefabUtility.prefabInstanceUpdated -= PrefabInstanceUpdated;
        PrefabUtility.prefabInstanceUpdated += PrefabInstanceUpdated;
        EditorApplication.update -= Update;
        EditorApplication.update += Update;
    }

    private static void PrefabInstanceUpdated(GameObject instance)
    { 
        _waiting = true;
        _lastTime = DateTime.Now;
    }

    private static void Update()
    {
        if (!_waiting || DateTime.Now - _lastTime < TimeSpan.FromSeconds(0.25)) return;
        AssetDatabase.SaveAssets();
        Debug.Log("Prefab change detected. Project saved.");
        _waiting = false;
    }
}

In JS here is the code i use for saving prefabs, it’s not complete because above it there is some size normalizing code etc.

there are 2 working functions though:

function save (){
	var go = Selection.activeGameObject;
	
	var mt = go.GetComponent(MeshFilter).mesh;
	var word1 = Random.Range(0,pent.length-1);
	AssetDatabase.CreateAsset(mt, "Assets/savedplat/assets/" +"-= " + writeName + mt.vertices.length + pent[word1]+"_ " + ".asset"); 
	
	
	var prefab = EditorUtility.CreateEmptyPrefab("Assets/savedplat/prefabs/" + "-= " + writeName + mt.vertices.length + pent[word1]+"_ " + ".prefab");
	EditorUtility.ReplacePrefab(go, prefab);
	AssetDatabase.Refresh();
	
	var comptime = System.DateTime.Now.ToString("MM-dd_HH:mm:ss");
	print ("saved " +  "-= " + writeName + mt.vertices.length + pent[word1] + ".files......  time was: " +comptime);

}

function combine () {
	var go = Selection.activeGameObject;
	go.AddComponent(CombineChildrenExtended);
	yield new WaitForFixedUpdate (); 
	if( go.GetComponent(MeshFilter) == null ){
	go.AddComponent(MeshRenderer);}
	yield new WaitForFixedUpdate (); 
	 var run = go.GetComponent(CombineChildrenExtended);
	run.CallCombineOnAllChilds();
	yield WaitForSeconds (2.58);
	
	 var childs : int = go.transform.childCount;

    for (var i = childs - 1; i >= 0; i--)
    {
        Destroy(go.transform.GetChild(i).gameObject);
		}
var mesh = go.GetComponent(MeshFilter).mesh;
print("This gameObject currently contains vertices = " +mesh.vertices.length);
		yield WaitForSeconds (2);
 save () ;
}