Saving Modified Mesh

Hey Guys,

Thanks for any help in advanced. Im currently editing a mesh within an Editor script and saving the game object with its new mesh as a prefab. It works but not as I want it too and I was wondering if anyone could help. Please see the below code:

string meshFilePath = "Assets/Resources/Meshes/" + meshFilter.transform.name + ".asset";
                Mesh meshToSave = meshFilter.mesh;
                AssetDatabase.CreateAsset(meshToSave, meshFilePath);
                AssetDatabase.SaveAssets ();
                AssetDatabase.Refresh ();
                meshFilter.mesh = meshToSave;
                string filePath = "Assets/Resources/Prefabs/" + meshFilter.transform.name + ".prefab";
                PrefabUtility.CreatePrefab(filePath, meshFilter.gameObject, ReplacePrefabOptions.ConnectToPrefab);

the mesh in my meshFilter contains my procedurally generated mesh. A prefab and a mesh is created and saved into the relevant folders however… when you look at the prefab saved within resources the inspector says that the mesh filter in the inspector is using the mesh “Type mismatch”. If I drag the prefab into the hierarchy the mesh filter is suddenly using the mesh that I want but its not linked to the mesh that was saved out before creating the prefab. If someone could point out where I’m going wrong that would be great.

CreateAsset creates an asset based on the object passed in.

Basically it’s cloning ‘meshToSave’ to disk.

Thing is, you’re having the meshFilter reference ‘meshToSave’, which was the source of the copy… not the copy itself.

Try loading the asset that you created. After line 6 where you refresh the AssetDatabase put:

meshToSave = AssetDatabase.LoadAssetAtPath(meshFilePath, typeof(Mesh)) as Mesh;

Now ‘meshToSave’ will be the new asset.

thanks for your help but unfortunately it yields the same result. I thought it might be because I’m saving the mesh as “.asset” (as it mentions to do so in the docs?!)

This thread is a bit old but single google leads to it…
Accessing mesh property creates a new instance , but it does not work inside the editor because it is not serialized…
You need to set the sharedMesh property :
meshFilter.sharedMesh = meshToSave;

Another way of creating a prefab with a generated mesh, is storing the mesh inside the prefab itself. Here is an example (NOT TESTED):

/// <summary>
/// Create a prefab with an array of precedural generated meshes
/// </summary>
private GameObject CreatePrefab(Mesh[] meshes, Material[] materials, string prefabName, string outputPath)
{
    // Create container
    var gameObject = new GameObject(prefabName);

    // Create an actual meshfilter for every mesh
    for (int i = 0; i < meshes.Length; i++)
    {
        var mesh = meshes[i];
        var material = materials[i];

        // Create mesh container
        var subGO = new GameObject(mesh.name);
        subGO.transform.SetParent(gameObject.transform, false);

        // Set Mesh and Material
        subGO.AddComponent<MeshFilter>().sharedMesh = mesh;
        subGO.AddComponent<MeshRenderer>().sharedMaterial = material;
    }

    // Create a prefab to store the gameobject
    var filename = gameObject.name + ".prefab";
    var filepath = Path.Combine(outputPath, filename);
    filepath = AssetDatabase.GenerateUniqueAssetPath(filepath);
    GameObject rootPrefab = null;
    try
    {
        // Create prefab
        rootPrefab = PrefabUtility.CreatePrefab(filepath, gameObject);

        // Set prefab meshes
        for (int i = 0; i < meshes.Length; i++)
        {
            var childPrefab = rootPrefab.transform.GetChild(i);
            var filter = childPrefab.GetComponent<MeshFilter>();
            if (filter != null)
            {
                filter.sharedMesh = meshes[i];
                filter.sharedMesh.RecalculateBounds();

                // Store the mesh inside the prefab
                AssetDatabase.AddObjectToAsset(meshes[i], rootPrefab);
            }
        }
        AssetDatabase.SaveAssets();
    }
    catch
    {
        Debug.LogError(string.Format("Error creating prefab '{0}' at path '{1}'", filename, outputPath));
    }

    // Destroy temporal go
    DestroyImmediate(gameObject);
  
    return rootPrefab;
}
2 Likes