Help with Saving a ProBuilderMesh

Discussion and help for Easy Save 3
Post Reply
dromo
Posts: 3
Joined: Fri May 19, 2023 12:09 pm

Help with Saving a ProBuilderMesh

Post by dromo »

Hi,

I'm currently working on a Unity project using ProBuilder and I need to save and load a ProBuilderMesh. Specifically, I need to save and load the following data from a ProBuilderMesh:

Positions (IList<Vector3>)
Faces (IList<Face>)
Colors (IList<Color>)
SharedVertices (IList<SharedVertex>)
Tangents (IList<Vector4>)
Textures (IList<Vector2>)
UnwrapParameters (UnwrapParameters)
Vertex Array (Vertex[])

The primary challenge I'm encountering is with the Face and SharedVertex classes. Unfortunately, Easy Save 3 doesn't accept these as Types, which makes it difficult for me to directly save and load instances of these classes.

I've been trying to convert these classes to serializable formats, but the process has proven to be complex and difficult due to various reasons, such as inaccessible constructors and specific fields of these classes that are also not directly serializable.

I understand that ES3 supports customization of serialization through the use of ES3Type scripts. I tried to implement an ES3Type for the Face and SharedVertex classes but ran into difficulties due to the complexity of these classes.

I was wondering if anyone in the community, or from the support team, could provide any assistance or guidance on how to overcome these challenges. Are there specific ES3Types I could use or customize to handle the Face and SharedVertex classes? Are there other strategies I could employ to save and load these ProBuilder classes?

Any help would be greatly appreciated. Thank you in advance for your support!
User avatar
Joel
Moodkie Staff
Posts: 4846
Joined: Wed Nov 07, 2012 10:32 pm

Re: Help with Saving a ProBuilderMesh

Post by Joel »

Hi there, and thanks for getting in contact.

Unfortunately as I have no experience with ProBuilder or it's classes I wouldn't be able to assist directly with this. Generally it is the responsibility of the creator of the classes to make them serializable at runtime, and it's possible that they've intentionally made them non-serializable.

If you're able to send me the Face and SharedVertex classes via private message I may be able to see if there's anything obvious with those classes which mean they're not serializable at runtime, or assist with creating an ES3Type if they can be supported, but I'm afraid I can't make any guarantees.

All the best,
Joel
Joel @ Moodkie Interactive
Purchase Easy Save | Contact | Guides | Docs | Getting started
User avatar
Joel
Moodkie Staff
Posts: 4846
Joined: Wed Nov 07, 2012 10:32 pm

Re: Help with Saving a ProBuilderMesh

Post by Joel »

An update: I had a go at importing the ProBuilder classes and this is how to add support.

For the Face class it is as simple as:
  1. Go to Tools > Easy Save 3 > Types.
  2. Search 'Face'.
  3. Select the Face class which has the UnityEngine.ProBuilder namespace.
  4. Select all of the fields.
  5. Press Create ES3Type script.
I tested this was working using the following code:

Code: Select all

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.ProBuilder;

public class TestScript : MonoBehaviour
{
    void Start()
    {
        var faces = new List<Face>();
        faces.Add(new Face(new int[] { 1, 2 ,3 }));
        faces.Add(new Face(new int[] { 3, 2, 1 }));
        faces.Add(new Face(new int[] { 2, 3, 1 }));

        ES3.Save("faces", faces);
        foreach (var face in ES3.Load<List<Face>>("faces"))
            Debug.Log(face.indexes.Count);
    }
}
For the SharedVertex class, it's necessary to create a custom ES3Type. I generated an ES3Type file for SharedVertex in the same way as above and modified it to use the SharedVertex classes constructor:

Code: Select all

using UnityEngine.ProBuilder;

namespace ES3Types
{
	[UnityEngine.Scripting.Preserve]
	public class ES3UserType_SharedVertex : ES3ObjectType
	{
		public static ES3Type Instance = null;

		public ES3UserType_SharedVertex() : base(typeof(SharedVertex)){ Instance = this; priority = 1; }


		protected override void WriteObject(object obj, ES3Writer writer)
		{
			var instance = (SharedVertex)obj;
			writer.WritePrivateField("m_Vertices", instance);
		}

		protected override object ReadObject<T>(ES3Reader reader)
		{
            foreach (string propertyName in reader.Properties)
            {
                switch (propertyName)
                {
                    case "m_Vertices":
                        return new SharedVertex(reader.Read<System.Int32[]>());
                    default:
                        reader.Skip();
                        break;
                }
            }
            
			return null;
		}
	}
}
I tested this with the following code:

Code: Select all

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.ProBuilder;

public class TestScript : MonoBehaviour
{
    void Start()
    {
        var vertices = new List<SharedVertex>();
        vertices.Add(new SharedVertex(new int[] { 1, 2, 3 }));
        vertices.Add(new SharedVertex(new int[] { 3, 2, 1 }));
        vertices.Add(new SharedVertex(new int[] { 2, 1, 3 }));
        ES3.Save("vertices", vertices);
        foreach (var vertex in ES3.Load<List<SharedVertex>>("vertices"))
            Debug.Log(vertex);
    }
}
All the best,
Joel
Joel @ Moodkie Interactive
Purchase Easy Save | Contact | Guides | Docs | Getting started
Post Reply