Battlehub0x / RTE_Docs

This is a repository for Runtime Editor documentation, discussion and tracking features and issues.
https://assetstore.unity.com/packages/tools/modeling/runtime-editor-64806
9 stars 0 forks source link

[AssetDatabase] .proto schemes and protobuf.js #111

Open Battlehub0x opened 1 week ago

Battlehub0x commented 1 week ago

Hello, thanks for the awesome package. Is there a way to get the .proto schemes for the editor's serialized files? We would like to be able to read the files in JavaScript.

Battlehub0x commented 1 week ago

This is a good question. I created sample code that gets meta-types from a typemodel and uses typeModel.GetSchema to get the schema.

For some reason GetSchema throws exceptions when the class has enum fields, to solve this problem I added enums to the typemodel manually. I'm not sure if that makes the schema incompatible, though.

using Battlehub.Storage;
using ProtoBuf.Meta;
using System;
using UnityEngine;

public class GetSurrogatesSchema 
{
    // Start is called before the first frame update
    public void PrintSchema()
    {
#if UNITY_EDITOR
        var typeModel = SerializerBase<Guid, string>.RuntimeTypeModel;

        typeModel.Add(typeof(UnityEngine.UI.Navigation.Mode), false);
        typeModel.Add(typeof(UnityEngine.Events.UnityEventCallState), false);
        typeModel.Add(typeof(UnityEngine.Events.PersistentListenerMode), false);
        typeModel.Add(typeof(UnityEngine.MeshTopology), false);

        var types = typeModel.GetTypes();
        foreach (MetaType metaType in types)
        {
            var fields = metaType.GetFields();
            foreach (var field in fields)
            {
                if (field.MemberType.IsEnum)
                {
                    typeModel.Add(field.MemberType, false);
                }
            }

            try
            {
                Debug.Log($"{metaType.Type} -> {typeModel.GetSchema(metaType.Type)}");
            }
            catch (Exception e)
            {
                Debug.LogError($"{metaType.Type}");
                Debug.LogException(e);
            }
        }
#endif

    }
}

The serialized surrogates are written to the output stream one by one, preceded by two integers: the first is the length of the data in bytes, the second is an integer that represents the type.

  byte[] header1 = BitConverter.GetBytes(length);
  byte[] header2 = BitConverter.GetBytes(typeIndex);

  stream.Write(header1, 0, header1.Length);
  stream.Write(header2, 0, header2.Length);
  stream.Write(data, 0, data.Length);

On the one hand, this results in a custom format, but on the other hand, it should allow you to deserialize data selectively. For example, deserialize only TransformSurrogates.

Let me know if you will be able to do something with the above info. I will also try to understand the best way to do this and whether data can be deserialized using the schema returned by typeModel.GetSchema.

happy-turtle commented 4 days ago

Thanks for looking into it! 🙌 I tried logging the schemas and that worked fine so far. I still need to try and actually use the schema for deserialization, I will post my findings here once I get to work on it.