Solution: Save a prefab with a generated mesh(es) without creating assets.

Hey guys, I’ve seen this topic many times and ran into this myself we I started making procedural stuff for my game. When we generate a mesh and want to bake it into a prefab (like a pre-fractured wall), Unity won’t serialize the mesh.
The most common solution is to save the mesh into assets and it’s ok. But in an instance when we have generated tens/hundreds of meshes which need to be individual pieces of something , saving them all takes a lot of time and is kinda pointless. So I decided to share a simple script that will serialize and recreate your meshes once you save a prefab and drag it into the scene/instantiate. Hopefully it will help some beginners.

#if UNITY_EDITOR
using UnityEditor;
#endif
using UnityEngine;

namespace TheTide.utils
{
    [ExecuteInEditMode]
    [RequireComponent(typeof(MeshFilter))]
    public class SerializeMesh : MonoBehaviour
    {
        [HideInInspector] [SerializeField] Vector2[] uv;
        [HideInInspector] [SerializeField] Vector3[] verticies;
        [HideInInspector] [SerializeField] int[] triangles;
        [HideInInspector] [SerializeField]bool serialized = false;
        // Use this for initialization

        void Awake()
        {
            if (serialized)
            {
                GetComponent<MeshFilter>().mesh = Rebuild();
            }
        }

        void Start()
        {
            if (serialized) return;

            Serialize();
        }

        public void Serialize()
        {
            var mesh = GetComponent<MeshFilter>().mesh;

            uv = mesh.uv;
            verticies = mesh.vertices;
            triangles = mesh.triangles;

            serialized = true;
        }

        public Mesh Rebuild()
        {
            Mesh mesh = new Mesh();
            mesh.vertices = verticies;
            mesh.triangles = triangles;
            mesh.uv = uv;
           
            mesh.RecalculateNormals();
            mesh.RecalculateBounds();

            return mesh;
        }
    }

#if UNITY_EDITOR
    [CustomEditor(typeof(SerializeMesh))]
    class SerializeMeshEditor : Editor
    {
        SerializeMesh obj;

        void OnSceneGUI()
        {
            obj = (SerializeMesh)target;
        }

        public override void OnInspectorGUI()
        {
            base.OnInspectorGUI();

            if (GUILayout.Button("Rebuild"))
            {
                if (obj)
                {
                    obj.gameObject.GetComponent<MeshFilter>().mesh = obj.Rebuild();
                }
            }

            if (GUILayout.Button("Serialize"))
            {
                if (obj)
                {
                   obj.Serialize();
                }
            }
        }
    }
#endif
}

Just create a new script called SerializeMesh and paste it, add the script to a GO with a mesh u want to serialize and you’re done.

Cheers.

13 Likes

Thank you!!! Man you are a saviour, this is what I really needed and were going to write a script. Save me a ton of work!!! Thanks again.

Thank you , you are a genius.

You can also serialize the mesh into a string and store it in a field (or array).

This is wonderful! Thank you so very much!

I think I must be missing the important step since this doesn’t work how I expected. I was expecting to be able to assign a mesh at runtime to an instance of a prefab and the mesh to be retained by the prefab once I returned to the editor? I suspect I don’t understand the “recreate the your meshes once you save the prefab”.

What I’ve done is:

(1) Created a prefab with a meshfilter, mesh renderer and the script.
(2) At runtime in playmode assigned the generated mesh to an instance of the prefab.
(3) Exited playmode back to the editor. No mesh is retained in the prefab or its instance.

Can someone give a clue on how to implement?

Not sure why you’re trying to save to an instance of a prefab during runtime, since during runtime a instance of a prefab is just a instantiated game object…

I want to save a prefab with a mesh generated at runtime. This serialisation code suggests it does that. I’ve tried applying the mesh to a prefab in the scene and to a game object instantiated from a prefab, but neither retain the mesh once you exit playmode. How did you save a mesh using this serialisation code? I am clearly missing something important in implementing it.

Did you run Serialize()?

Unless I am missing some crucial step this code doesn’t seem to work. SerializeField doesn’t seem to preserve data generated at runtime once back in the editor (the code also throws an error unless you use sharedMesh instead of mesh).

I’ve added debug.Log to Awake(), Start(), Serialize() to print to the console the length of the array verticies. This array is populated from the mesh in Serialize() at runtime and then used in Awake() to rebuild the mesh in the editor. Only the array is cleared on exiting playmode.

Here’s what I did: I have a prefab with the script as a component and a meshfilter. During runtime I create a mesh and apply to the prefabs meshfilter, then I call Serialize(). Then I exit playmode back to the editor. This is what it prints.

On pressing play
Awake: Array length 0 - this is expected no mesh has yet been added to the meshfilter
Start: Array length 0 - this is expected no mesh has yet been added to the meshfilter
Serialize: Array length 73 - this has added the mesh to the Vector3[ ] verticies within the prefab.
Exit back to editor
Awake: Array length 0 - data in verticies was cleared
Start: Array length 0 - data in verticies was cleared.

Lol i forgot that I even posted this, nice to see that some ppl find it useful.

As i understand what you’re trying to do, it won’t be possible because Unity itself doesn’t serialize fields in prefabs during runtime. They just reset to their original state after you exit playmode. You should generate your mesh in editmode. If you have a runtime mesh modifying app you need to serialize it yourself , whether its a file, an asset or a scriptable object or something else.

1 Like

Thank you, you saved my project!

It’s kind of late to say, but man this is gold.Thank you for sharing, I also learn something new ! For some reason in Unity 2019.4 the prefabs did not include the meshes, didn’t happened in the previous version. Saved the project and deadline.

Hey, that’s a clever trick!

However I feel I should point out one drawback: if you have 100 instances of the same object with this script on it, this is going to result in 100 identical meshes in memory. Whereas with the standard approach of saving the modified mesh to the asset database, all instances would share just one copy of the mesh. Meshes can get pretty big, so this could really matter on memory-constrained devices (like Quest).

1 Like

that’s true, you could build only one mesh and refer instances and set their sharedmeshes to the one serialized (the mesh which is rebuilt on first awake in a prefab and other would not build a new mesh but just set a shared mesh to the one you rebuilt at first) I’ve used this for a destructible prebaked building and it would require serializing around 2000 small meshes per building. That’s why I found it useful :wink:

Isn’t it better to save the mesh? Because now we need to rebuild our mesh everytime the game/scene starts

Hello, for some reason nothing works for me :frowning:
I have generated pieces of the object, and when I add your script to these pieces and click Serialize, nothing just happens, I still can’t save the pieces to the prefab
Am I doing something wrong?

Did you solve it? Are you trying to use it for MeshFilter or MeshCollider? I needed it for MeshCollider, so I modified the code and replaced every mention of MeshFilter to MeshCollider and it worked. You might need to press Serialize on each collider and make sure you are not in prefab mode. You can apply changes to prefab after serializing colliders.

Hello,
Can you please tell me how I use your script because I added it to my prefab (added a C# script component and pasted it) but I am only getting errors:

What I have is several prefabs using the same source mesh and I just need those prefabs to use instances or copies of that same source mesh.

9144766--1270762--a5.jpg

Thanks a lot!!