Giter Site home page Giter Site logo

odin-serializer's Introduction


Odin Serializer

Fast, robust, powerful and extendible .NET serializer built for Unity

OdinSerializer is an open-source version of the custom serializer built for and used by Odin - Inspector & Serializer


Sirenix Twitter Discord server Inspect all data with Odin Serializer Download Donate


Used in hundreds of games and supported by Asset Store developers such as

DevDog ParadoxNotion Ludiq


Performance charts and comparisons

OdinSerializer compares very well to many popular serialization libraries in terms of performance and garbage allocation, while providing a superior feature-set for use in Unity.

The performance graphs in this section are profiled with OdinSerializer's binary format.

Odin Serializer Unity JSON Full Serializer Binary Formatter JSON.NET Protobuf-net
Open Source ✔️ ✔️ ✔️ ✔️
Cross Platform ✔️ ✔️ ✔️ ✔️ ✔️ ✔️
Out of the box Unity Support ✔️ ✔️ ✔️
Supports Unity structs ✔️ ✔️ ✔️
Binary Formatter ✔️ ✔️ ✔️
Json Formatter ✔️ ✔️ ✔️ ✔️
Merge-friendly data in Unity objects ✔️
Interfaces ✔️ ✔️ ✔️ ✔️ ✔️
Properties ✔️ ✔️ ✔️ ✔️
Polymorphism ✔️ ✔️ ✔️ ✔️ ✔️
Generics ✔️ ✔️ ✔️ ✔️ ✔️
Dictionaries ✔️ ✔️ ✔️ ✔️ ✔️
Circular References ✔️ ✔️ ✔️ ✔️ ✔️
Delegates ✔️ ✔️
Multi-dimensional arrays ✔️ ✔️ ✔️
Extendable ✔️ ✔️ ✔️ ✔️ ✔️
Renaming Members ✔️ ✔️ ✔️ ✔️ ✔️ ✔️
Renaming Types ✔️ ✔️ ✔️ ✔️ ✔️ ✔️
IL Optimized ✔️ - -
Supports .NET interfaces ✔️ ✔️ ?
Supports .NET callback attributes ✔️ ✔️ ✔️ ✔️

Serialization of a simple object with no polymorphism

Benchmark

Serialization of a complex object with lots of polymorphism

*Unity JsonUtility has been excluded from this benchmark because it supports neither polymorphism or dictionaries

Benchmark

Serialization of various large arrays and lists

Benchmark

Garbage allocation of the 3 tests above

Benchmark

How to get started

There are many different use cases for OdinSerializer. If you just need a serialization library to use in your own private project, we can recommend that you simply use it out of the box. If you would like to make your own tweaks and builds, or if you intend to include OdinSerializer in a package that you are distributing, you would be better served by forking the repository.

Using OdinSerializer out of the box

To use OdinSerializer as-is, simply head to the download page on our website to download the latest commit as a .unitypackage file, and import the package into your Unity project. OdinSerializer will then be in your project, ready to use.

Forking OdinSerializer

Note: currently, working with and building the OdinSerializer project has only been tested on Windows machines, using Visual Studio.

To get started, you may want to read GitHub's guide to forking, to get the basics of forking down.

Once you've forked OdinSerializer, you can start making your own changes to the project. Perhaps you want to add a feature, or tweak a part of it to suit your own needs better.

If you intend to include OdinSerializer in one of your own product distributions, you should modify all source files using a tool like search and replace to move the OdinSerializer namespace into an appropriate namespace for your project, and rename the .dll's that are built. This is to avoid namespace and assembly conflicts in the cases where multiple different assets in the same project all use possibly differing versions of OdinSerializer. For example, you might globally rename "OdinSerializer" to "MyProject.Internal.OdinSerializer", and also have the .dll's renamed to "MyProject.Internal.OdinSerializer.dll".

Here's a goto list of things that need to be renamed during this process:

  • OdinSerializer.csproj: AssemblyName and RootNamespace and XML doc path.
  • OdinBuildAutomation.cs: Namespace, and assembly name strings in the static constructor.
  • Namespaces in the entire OdinSerializer project (search and replace is your friend).
  • The link.xml file included in the AOT folder.

Building OdinSerializer

The OdinSerializer project is set up as an independent code project that lives outside of Unity, and which can compile assemblies for use inside of a Unity project. Its build settings are set up to use a specific MSBuild distributable (Roslyn compiler) to build assemblies that are Unity-compatible, and the pdb2mdb tool to convert .pdb symbol files to .mdb symbol files to support proper step debugging in Unity. Simply building with the default MSBuild versions that ship with many recent distributions of Visual Studio appears to cause instant runtime crashes in some versions of Unity the moment the code enters an unsafe context.

The easiest way to build and test OdinSerializer, however, is to open the Build folder as a Unity project (any Unity version at or above 5.3 should work). When open, you will see three buttons in the project scene view: "Compile with debugging", "Compile release build" and "Open solution".

Compile with debugging compiles an assembly into the open project, along with the proper symbol files for step debugging. Once this assembly is imported by Unity, you can step debug OdinSerializer by attaching a Visual Studio instance to it.

Compile release build compiles three different OdinSerializer assembly variants with release optimizations. The three assemblies are for use in respectively the editor, in builds with JIT support (Windows/Mac/Linux), and in AOT builds (IL2CPP). The OdinSerializer Unity project also includes one script file, OdinSerializerBuildAutomation.cs, which automates setting the import settings of these three assemblies correctly during the build process based on the current target platform and scripting backend so that the correct assembly is used for that build, as well as automatically scanning the project and generating AOT support for types that need it, if the build is AOT compiled. We encourage you to modify this file or otherwise adapt it to suit your own particular automation needs.

Open solution simply opens the OdinSerializer solution file using the default application.

Basic usage of OdinSerializer

This section will not go into great detail about how OdinSerializer works or how to configure it in advanced ways - for that, see the technical overview further down. Instead, it aims to give a simple overview of how to use OdinSerializer in a basic capacity.

There are, broadly, two different ways of using OdinSerializer:

Serializing regular C# objects

You can use OdinSerializer as a standalone serialization library, simply serializing or deserializing whatever data you give it, for example to be stored in a file or sent over the network. This is done using the SerializationUtility class, which contains a variety of methods that wrap OdinSerializer for straight-forward, easy use.

Example: Serializing regular C# objects
using OdinSerializer;

public static class Example
{
	public static void Save(MyData data, string filePath)
	{
		byte[] bytes = SerializationUtility.SerializeValue(data, DataFormat.Binary);
		File.WriteAllBytes(bytes, filePath);
	}
	
	public static MyData Load(string filePath)
	{
		byte[] bytes = File.ReadAllBytes(filePath);
		return SerializationUtility.DeserializeValue<MyData>(bytes, DataFormat.Binary);
	}
}

Note that you cannot save references to Unity objects or assets down to a file in this manner. The only way to handle this is to ask for a list of all encountered UnityEngine.Object references when serializing, and then pass that list of references back into the system when deserializing data.

Example: Serializing regular C# objects containing Unity references
using OdinSerializer;

public static class Example
{
	public static void Save(MyData data,  string filePath, ref List<UnityEngine.Object> unityReferences)
	{
		byte[] bytes = SerializationUtility.SerializeValue(data, DataFormat.Binary, out unityReferences);
		File.WriteAllBytes(bytes, filePath);
		
		// The unityReferences list will now be filled with all encountered UnityEngine.Object references, and the saved binary data contains index pointers into this list.
		// It is your job to ensure that the list of references stays the same between serialization and deserialization.
	}
	
	public static MyData Load(string filePath, List<UnityEngine.Object> unityReferences)
	{
		byte[] bytes = File.ReadAllBytes(filePath);
		return SerializationUtility.DeserializeValue<MyData>(bytes, DataFormat.Binary, unityReferences);
	}
}

Extending UnityEngine.Object serialization

You can also use OdinSerializer to seamlessly extend the serialization of Unity's object types, such as ScriptableObject and MonoBehaviour. There are two general ways of doing this, one of which is manual and requires a few lines of code to implement, and one of which is very easy to implement, but exhibits only the default behaviour.

The easier approach is to simply derive your type from one of many pre-created UnityEngine.Object-derived types that OdinSerializer provides, that have the above behaviour implemented already. Note that doing this will have the default behaviour of not serializing fields that Unity will serialize.

Example: Easily extending UnityEngine.Object serialization
using OdinSerializer;

public class YourSpeciallySerializedScriptableObject : SerializedScriptableObject
{
	public Dictionary<string, string> iAmSerializedByOdin;
	public List<string> iAmSerializedByUnity;
}

The manual method requires that you implement Unity's ISerializationCallbackReceiver interface on the UnityEngine.Object-derived type you want to extend the serialization of, and then use OdinSerializer's UnitySerializationUtility class to apply Odin's serialization during the serialization callbacks that Unity invokes at the appropriate times.

Example: Manually extending UnityEngine.Object serialization
using UnityEngine;
using OdinSerializer;

public class YourSpeciallySerializedScriptableObject : ScriptableObject, ISerializationCallbackReceiver
{
	[SerializeField, HideInInspector]
	private SerializationData serializationData;

	void ISerializationCallbackReceiver.OnAfterDeserialize()
	{
		// Make Odin deserialize the serializationData field's contents into this instance.
		UnitySerializationUtility.DeserializeUnityObject(this, ref this.serializationData, cachedContext.Value);
	}

	void ISerializationCallbackReceiver.OnBeforeSerialize()
	{
		// Whether to always serialize fields that Unity will also serialize. By default, this parameter is false, and OdinSerializer will only serialize fields that it thinks Unity will not handle.
		bool serializeUnityFields = false;
		
		// Make Odin serialize data from this instance into the serializationData field.
		UnitySerializationUtility.SerializeUnityObject(this, ref this.serializationData, serializeUnityFields, cachedContext.Value);
	}
}

NOTE: If you use OdinSerializer to extend the serialization of a Unity object, without having an inspector framework such as Odin Inspector installed, the Odin-serialized fields will not be rendered properly in Unity's inspector. You will either have to acquire such a framework, or write your own custom editor to be able to inspect and edit this data in Unity's inspector window.

Additionally, always remember that Unity doesn't strictly know that this extra serialized data exists - whenever you change it from your custom editor, remember to manually mark the relevant asset or scene dirty, so Unity knows that it needs to be re-serialized.

Finally, note that prefab modifications will not simply work by default in specially serialized Components/Behaviours/MonoBehaviours. Specially serialized prefab instances may explode and die if you attempt to change their custom-serialized data from the parent prefab. OdinSerializer contains a system for managing an object's specially-serialized prefab modifications and applying them, but this is an advanced use of OdinSerializer that requires heavy support from a specialised custom editor, and this is not covered in this readme.

How to contribute

We are taking contributions under the Apache 2.0 license, so please feel free to submit pull requests. Please keep in mind the following rules when submitting contributions:

  • Follow the pre-existing coding style and standards in the OdinSerializer code.
  • If you work in your own fork with a modified OdinSerializer namespace, please ensure that the pull request uses the correct namespaces for this repository and otherwise compiles right away, so we don't need to clean that sort of stuff up when accepting the pull request.

We are taking any contributions that add value to OdinSerializer without also adding undue bloat or feature creep. However, these are the areas that we are particularly interested in seeing contributions in:

Bugfixes

  • We would be very grateful if you could submit pull requests for any bugs that you encounter and fix.

Performance

  • General overall performance: faster code is always better, as long as the increase in speed does not sacrifice any robustness.
  • Json format performance: the performance of the json format (JsonDataWriter/JsonDataReader) is currently indescribably awful. The format was originally written as a testbed for use during the development of OdinSerializer, since it is human-readable and thus very useful for debugging purposes, and has remained largely untouched since.
  • EnumSerializer currently allocates garbage via boxing serialized and deserialized enum values. As such, serializing enums always results in unnecessary garbage being allocated. Any approaches for fixing this would be most welcome. Some unsafe code may be required, but we haven't yet had time to really look into this properly.

Testing

  • A thorough set of standalone unit tests. Odin Inspector has its own internal integration tests for OdinSerializer, but currently we have no decent stand-alone unit tests that work solely with OdinSerializer.

Technical Overview

The following section is a brief technical overview of the working principles of OdinSerializer and many of its bigger features. First, however, let's have a super brief overview, to give some context before we begin.

This is how OdinSerializer works, on the highest level:

  • Data to be written to or read from is passed to a data writer/reader, usually in the form of a stream.
  • The data writer/reader is passed to a serializer, along with a value to be serialized, if we are serializing.
  • If the value can be treated as an atomic primitive, the serializer will write or read that directly using the passed data writer/reader. If the value is "complex", IE, it is a value that consists of other values, the serializer will get and wrap the use of a formatter to read or write the value.

"Stack-only", forward-only

OdinSerializer is a forward-only serializer, meaning that when it serializes, it writes data immediately as it inspects the object graph, and when it deserializes, it recreates the object graph immediately as it parses the data. The serializer only ever moves forward - it cannot "go back" and look at previous data, since we retain no state and are doing everything on the fly, as we move forward. Unlike some other serializers, there is no "meta-graph" data structure that is allocated containing all the data to be saved down later.

This means that we can serialize and deserialize data entirely without allocating anything on the heap, meaning that after the system has run once and all the writer, reader, formatter and serializer instances have been created, there will often be literally zero superfluous GC allocations made, depending on the data format used.

Data writers and readers

Data writers and readers are types that implement the IDataReader and/or IDataWriter interfaces. They abstract the writing and reading of strongly typed C# data in the form of atomic primitives, from the actual raw data format that the data is written into and read from. OdinSerializer currently ships with data readers and writers that support three different formats: Json, Binary and Nodes.

Data writers and readers also contain a serialization or deserialization context, which is used to configure how serialization and deserialization operates in various ways.

Atomic primitives

An atomic primitive (or merely a primitive), in the context of OdinSerializer, is a type that can be written or read in a single call to a data writer or reader. All other types are considered complex types, and must be handled by a formatter that translates that type into a series of atomic primitives. You can check whether something is an atomic primitive by calling FormatterUtilities.IsPrimitiveType(Type type).

The following types are considered atomic primitives:

  • System.Char (char)
  • System.String (string)
  • System.Boolean (bool)
  • System.SByte (sbyte)
  • System.Byte (byte)
  • System.Short (short)
  • System.UShort (ushort)
  • System.Int (int)
  • System.UInt (uint)
  • System.Long (long)
  • System.ULong (ulong)
  • System.Single (float)
  • System.Double (double)
  • System.Decimal (decimal)
  • System.IntPtr
  • System.UIntPtr
  • System.Guid
  • All enums

Serializers and formatters

This is an important distinction - serializers are the outward "face" of the system, and are all hardcoded into the system. There is a hardcoded serializer type for each atomic primitive, and a catch-all ComplexTypeSerializer that handles all other types by wrapping the use of formatters.

Formatters are what translates an actual C# object into the primitive data that it consists of. They are the primary point of extension in OdinSerializer - they tell the system how to treat various special types. For example, there is a formatter that handles arrays, a formatter that handles multi-dimensional arrays, a formatter that handles dictionaries, and so on.

OdinSerializer ships with a large number of custom formatters for commonly serialized .NET and Unity types. An example of a custom formatter might be the following formatter for Unity's Vector3 type:

using OdinSerializer;
using UnityEngine;

[assembly: RegisterFormatter(typeof(Vector3Formatter))]
	
public class Vector3Formatter : MinimalBaseFormatter<Vector3>
{
	private static readonly Serializer<float> FloatSerializer = Serializer.Get<float>();

	protected override void Read(ref Vector3 value, IDataReader reader)
	{
		value.x = FloatSerializer.ReadValue(reader);
		value.y = FloatSerializer.ReadValue(reader);
		value.z = FloatSerializer.ReadValue(reader);
	}
	
	protected override void Write(ref Vector3 value, IDataWriter writer)
	{
		FloatSerializer.WriteValue(value.x, writer);
		FloatSerializer.WriteValue(value.y, writer);
		FloatSerializer.WriteValue(value.z, writer);
	}
}

All complex types that do not have a custom formatter declared are serialized using either an on-demand emitted formatter, or if emitted formatters are not available on the current platform, using a fallback reflection-based formatter. These "default" formatters use the serialization policy set on the current context to decide which members are serialized.

Serialization policies

Serialization policies are used by non-custom formatters (emitted formatters and the reflection formatter) to decide which members should and should not be serialized. A set of default policies are provided in the SerializationPolicies class.

External references

External references are a very useful concept to have. In short, it's a way for serialized data to refer to objects that are not stored in the serialized data itself, but should instead be fetched externally upon deserialization.

For example, if an object graph refers to a very large asset such as a texture, stored in a central asset database, you might not want the entire texture to be serialized down along with the graph, but might instead want to serialize an external reference to the texture, which would then be resolved again upon deserialization. When working with Unity, this feature is particularly useful, as you will see in the next section.

External references in OdinSerializer can be either by index (int), by guid (System.Guid), or by string, and are used by implementing the IExternalIndexReferenceResolver, IExternalGuidReferenceResolver or IExternalStringReferenceResolver interfaces, and setting a resolver instance on the context that is set on the current data reader or writer.

All reference types (except strings, which are treated as atomic primitives) can potentially be resolved externally, and all available external reference resolvers in the current context will be queried for each encountered reference type object as to whether or not that object ought to be serialized as an external reference.

How OdinSerializer works in Unity

OdinSerializer comes with a built-in Unity integration for use with types derived from Unity's special UnityEngine.Object class. This integration comes primarily in the form of the UnitySerializationUtility class, and the various convenience classes to derive from, that implement OdinSerializer using UnitySerializationUtility. Each such class derives from a given commonly used UnityEngine.Object type:

  • SerializedUnityObject : UnityEngine.Object
  • SerializedScriptableObject : UnityEngine.ScriptableObject
  • SerializedComponent : UnityEngine.Component
  • SerializedBehaviour : UnityEngine.Behaviour
  • SerializedMonoBehaviour : UnityEngine.MonoBehaviour
  • SerializedNetworkBehaviour : UnityEngine.NetworkBehaviour
  • SerializedStateMachineBehaviour : UnityEngine.StateMachineBehaviour

Deriving from any of these types means that your derived type will be serialized using UnitySerializationUtility. Note that this will, by default, not serialize all serialized members on your derived type. These convenience types use the SerializationPolicies.Unity policy to select members for serialization, and also have the added behaviour that they will not serialize any members on the derived type that Unity would usually serialize. Note that this only applies directly on the root members of the serialized UnityEngine.Object-derived type. Take the following example:

// This is the component you put on a GameObject. It is THIS component, and only this component, that decides whether or not something is serialized by Odin
public class MyMonoBehaviour : SerializedMonoBehaviour // Inheriting the component from SerializedMonoBehaviour means we use Odin's serialization
{
    public Dictionary<string, string> someDictionary; // Will be serialized by Odin

    [SerializeField]
    private SomeClass someClass1; // Will be serialized by Unity, NOT Odin. "someClass1.someString" will be serialized, but "someClass1.someDict" will NOT be serialized. Polymorphism is NOT supported. Null values are NOT supported.

    [OdinSerialize]
    private SomeClass someClass2; // Will be serialized by Odin, NOT Unity. Both "someClass2.someString" and "someClass2.someDict" will be serialized. Both polymorphism and null values are supported.
}

[Serializable]
public class SomeClass // No matter what you inherit from here, it makes no difference at all to the serialization of this class - that is decided "higher up" in the component itself
{
    public string someString;
    public Dictionary<string, string> someDict;
}

If you wish to change this behaviour, you must implement your own special serialized UnityEngine.Object type using Unity's ISerializationCallbackReceiver interface, and manually change either the policy or the arguments passed to UnitySerializationUtility. For example:

using UnityEngine;
using OdinSerializer;
using OdinSerializer.Utilities;

public class YourMonoBehaviour : MonoBehaviour, ISerializationCallbackReceiver
{
	[SerializeField, HideInInspector]
	private SerializationData serializationData;

	void ISerializationCallbackReceiver.OnAfterDeserialize()
	{
		using (var cachedContext = Cache<DeserializationContext>.Claim())
		{
			cachedContext.Value.Config.SerializationPolicy = SerializationPolicies.Everything;
			UnitySerializationUtility.DeserializeUnityObject(this, ref this.serializationData, cachedContext.Value);
		}
	}

	void ISerializationCallbackReceiver.OnBeforeSerialize()
	{
		using (var cachedContext = Cache<SerializationContext>.Claim())
		{
			cachedContext.Value.Config.SerializationPolicy = SerializationPolicies.Everything;
			UnitySerializationUtility.SerializeUnityObject(this, ref this.serializationData, serializeUnityFields: true, context: cachedContext.Value);
		}
	}
}

Finally, it should be noted that the UnitySerializationUtility class always sets a UnityReferenceResolver as an external index resolver. This external reference resolver ensures that all references to Unity objects encountered in the data to serialize become external references, which are shunted into a list in the SerializationData struct for Unity to serialize, and later used to link the external references back up to the correct Unity instance.

This is done because there is no way for Odin to actually serialize and later reconstruct most UnityEngine.Object-derived types, and therefore, we have established it as a hard rule that we will never even try to do so.

AOT Support details

OdinSerializer contains two utility classes, AOTSupportUtilities and AOTSupportScanner, for providing support for AOT (Ahead-Of-Time) compiled platforms such as IL2CPP and Mono AOT. These utilities can be used to scan the entire project (or merely parts of it) and generate a list of types that are serialized by OdinSerializer, and they can take a list of types and create a .dll file in your project that ensures that there will be serialization support for all the given types in an AOT build.

To automate this process of AOT support, you can use Unity's IPreProcessBuild/IPreProcessBuildWithReport and IPostProcessBuild/IPostProcessBuildWithReport interfaces to create an AOT support dll upon building, and delete it again after building. (Note that this only becomes possible in Unity 5.6, where IPreProcessBuild was introduced.)

OdinSerializer already includes one script file in the Unity project, OdinSerializerBuildAutomation.cs, which automates setting the import settings of OdinSerializer's three assembly variants correctly during the build process based on the current target platform and scripting backend, as well as automatically scanning the project and generating AOT support for types that need it, if the build is AOT compiled. We encourage you to modify this file to suit your own particular automation needs.

odin-serializer's People

Contributors

bjarkeck avatar jperryoddgames avatar legionspitfire avatar schwapo avatar sp-jordi-vilalta avatar torvestergaard avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

odin-serializer's Issues

Reading negative SByte values from Binary DataFormat returns 0

Hi, there is a minor bug with the BinaryDataReader which makes all negative sbyte values get read as 0. The repro is simple:

struct SerializedValue
{
    public sbyte value;
}

// And then in a method
byte[] bytes = SerializationUtility.SerializeValue<SerializedValue>(new SerializedValue() { value = -1 }, DataFormat.Binary);
Debug.Log(SerializationUtility.DeserializeValue<SerializedValue>(bytes, DataFormat.Binary).value);

This will log 0 in Unity instead of the expected value of -1. Switching to use JSON data format logs -1 as expected. The above code only uses the struct since JSON doesn't serialize the plain sbyte without the container type.

The cause of this issue is that the BinaryDataWriter class will convert an sbyte to a byte in an unchecked block in the WriteSByte method and serialize that byte value directly, but the BinaryDataReader will read that value in ReadSByte from a long and cast it to an sbyte inside a checked block. This means that if for instance you store a sbyte value of -1, it will be serialized as the unsigned byte value of 255. Then when you attempt to read the value it will attempt to cast that long value of 255 to an sbyte value of -1 which will throw an exception in the checked block since 255 would overflow to get to -1 which gets caught and makes the method return 0.

An easy fix for this is would be to change the checked block to an unchecked block in the ReadSByte() function in the BinaryDataReader. But that means any values which are supposed to be other types that fall out of the range of sbyte will just overflow into odd sbyte values. I didn't make a PR for this since I'm not sure how you'd want to approach this since sbyte is handled a bit differently than the other types.

AOT scanner does absolutely nothing

Hello

I've been fighting with AOT generation for several hours now and now it just feels like the AOT scanner is just broken.
I have a simple struct that I want to serialize. The struct itself also contains a few other structs. Nothing super advanced. It's all just ints, strings, etc.
I have to add every single struct I want to serialize manually when generating an AOT dll. Is this really how it's supposed to be? I even had to add UnityEngine.Vector3Int!

This is my code for generating the dll file.

public void OnPreprocessBuild(BuildReport report)
{
    if (AOTSupportUtilities.ScanProjectForSerializedTypes(out List<Type> supportedTypes))
    {
        supportedTypes.Add(typeof(SaveData));
        supportedTypes.Add(typeof(ObjectData));
        supportedTypes.Add(typeof(ObjectData[]));
        supportedTypes.Add(typeof(ComponentData));
        supportedTypes.Add(typeof(ComponentData[]));
        supportedTypes.Add(typeof(PropertyData));
        supportedTypes.Add(typeof(PropertyData[]));
        supportedTypes.Add(typeof(Vector2Int));
        supportedTypes.Add(typeof(Vector3Int));

        AOTSupportUtilities.GenerateDLL(Application.dataPath + "/Plugins/", "GeneratedAOT", supportedTypes);
    }
}

Am I missing something here or is this by design?

I'm also sorry if this comes up as aggressive, I'm just really tired after working with this for several hours. I'm loving the rest though when it actually works in the editor and I don't want to give up on it just yet!

EDIT: I forgot to mention, checking the generated dll in an IL inspector shows that it's pretty much empty unless I manually add all this stuff.

Odin deserialization, excluding unity deserializationy

If I want to deserialize the data field(serializationData) after Odin serialization, what should I do? (serializationutility. Deserializevalue() is to deserialize the double serialization result after the default serialization of serializationdata field by unity. I only need to deserialize the data after Odin serialization)

(AOT) ScanProjectForSerializedTypes only returns 2 types and has asserts unity 2018.3.0f2

Asserts

[Assert] Assertion failed on expression: 'GetApplication().MayUpdate()'
UnityEditor.SceneManagement.EditorSceneManager:NewScene(NewSceneSetup, NewSceneMode)
AOTSupportScanner.ScanScenes() C:/Sirenix/OdinSerializer/OdinSerializer/Unity Integration/AOTSupportScanner.cs:257

AOTSupportScanner.ScanBuildScenes() C:/Sirenix/OdinSerializer/OdinSerializer/Unity Integration/AOTSupportScanner.cs:179

AOTSupportUtilities.ScanProjectForSerializedTypes() C:/Sirenix/OdinSerializer/OdinSerializer/Unity Integration/AOTSupportUtilities.cs:48

OdinBuildAutomation.OnPreprocessBuild() Assets/Plugins/Sirenix/Odin Serializer/OdinBuildAutomation.cs:74

OdinPreBuildAutomation.OnPreprocessBuild() Assets/Plugins/Sirenix/Odin Serializer/OdinBuildAutomation.cs:116

GUIUtility.ProcessEvent()

And

[Assert] Assertion failed on expression: '!performAutorepaint || GetApplication().MayUpdate()'
UnityEditor.SceneManagement.EditorSceneManager:NewScene(NewSceneSetup, NewSceneMode)
AOTSupportScanner.ScanScenes() C:/Sirenix/OdinSerializer/OdinSerializer/Unity Integration/AOTSupportScanner.cs:257

AOTSupportScanner.ScanBuildScenes() C:/Sirenix/OdinSerializer/OdinSerializer/Unity Integration/AOTSupportScanner.cs:179

AOTSupportUtilities.ScanProjectForSerializedTypes() C:/Sirenix/OdinSerializer/OdinSerializer/Unity Integration/AOTSupportUtilities.cs:48

OdinBuildAutomation.OnPreprocessBuild() Assets/Plugins/Sirenix/Odin Serializer/OdinBuildAutomation.cs:74

OdinPreBuildAutomation.OnPreprocessBuild() Assets/Plugins/Sirenix/Odin Serializer/OdinBuildAutomation.cs:116

GUIUtility.ProcessEvent()

Am trying to build for switch using il2cpp

two types that were output
OdinBuildAutomation types csDelaunay.Voronoi
OdinBuildAutomation types csDelaunay.Voronoi[]

Note running the build when it tries to deserialize a file it complains that Vector2 wasnt added as a type.

AOT generate didn't generate any support serialized type on ScriptableObject.

public class DBImages : SerializedScriptableObject
{
 
    [OdinSerialize]
    Dictionary<Enum.ItemIdentity, string> _dbItem = new Dictionary<Enum.ItemIdentity, string>();

    [OdinSerialize]
    Dictionary<Enum.MonsterElement, string> _dbMonsterElement = new Dictionary<Enum.MonsterElement, string>();

    [OdinSerialize]
    Dictionary<PGGame.Enum.SkillIdentity, string> _dbSkill = new Dictionary<PGGame.Enum.SkillIdentity, string>();

	[OdinSerialize]
	Dictionary<Tactics.TacticCtrl.TacticsMode, string> _dbTactic = new Dictionary<Tactics.TacticCtrl.TacticsMode, string>();
    
    public static Sprite Get(Enum.ItemIdentity e)
    {
        
        
        try
        {
            DBImages db = DBImages.Instance;
            if (db == null)
                return null;

            if (!db._dbItem.ContainsKey(e))
                return null;
     
            try
            {
                return Resources.Load<Sprite>(db._dbItem[e]);
            }
            catch 
            {
                Debug.LogError("DBImages unable to load sprite at:" + db._dbItem[e]);
                return null; 
            }
        }
        catch(Exception er) {
            Debug.LogError(er.Message);
            return null; 
        }
        
    }

    public static Sprite Get(Enum.MonsterElement e)
    {
        if (!Instance._dbMonsterElement.ContainsKey(e))
            return null;

        return Resources.Load<Sprite>(Instance._dbMonsterElement[e]);
    }
    
    public static Sprite Get(PGGame.Enum.SkillIdentity e)
    {
        if (!Instance._dbSkill.ContainsKey(e))
            return null;

        return Resources.Load<Sprite>(Instance._dbSkill[e]);
    }

	public static Sprite Get(Tactics.TacticCtrl.TacticsMode e)
	{
		if (!Instance._dbTactic.ContainsKey(e))
			return null;
		return Resources.Load<Sprite>(Instance._dbTactic[e]);
    }

    


    #region Base Part
    public static readonly string kFileName = "DB.Images.asset";
    public static readonly string kFolder = "Assets/GeneratedScripts/Resources/";
    public static readonly string kFullPath = kFolder + kFileName;


    private static DB.DBImages _instance;

    public static DB.DBImages Instance
    {
        get{
            
            if (_instance == null)
            {
                try
                {
                    _instance = Resources.Load<DB.DBImages>(kFileName.RemoveFilenameExtension());
                }
                catch
                {
                    throw new Exception("Unable to load DB.Image"); 
                }
            }
            if (_instance == null)
            {
                Debug.LogWarning("DB.DBImages not found. Make sure it is created");
            }

            return _instance;
        }
    }

This is my code.
I tried many way and search many site to solve this but nothing work for me.
In AOT Generate's message box told It'll scan the entire project.
In reality , it just scan and get serialized type in Every Scene , not entire project.
It didn't get serialized type on ScriptableObject.(yes! It isn't Monobehavior , It can't be in any scene)
And it just leave me a empty support serialized types list.

AOT dll before building

Hi,

Does is it possible to use Odin's AOT generation feature to generate an AOT dll before building without odin inspector?

I'm trying to use odin-serializer in an UWP application.

Thanks for reply

Unity 2021.3 .NET Standard 2.0 API not supported, Out of the box.

I'm trying to test the odin-serializer on Unity 2021.3.12f1 on windows 10.

So just wondering if is this normal behavior for out of the box?

Assets\OdinSerializer\Utilities\Misc\EmitUtilities.cs(20,8): error CS1029: #error: 'Odin Inspector is incapable of compiling source code against the .NET Standard 2.0 API surface. You can change the API Compatibility Level in the Player settings.'

I didn't see any info in the readme that i need to switch APIs.
I switched the API to .Net framework. I get a lot of warnings similar too.

Assets\OdinSerializer\Unity Integration\UnitySerializationUtility.cs(832,87): warning CS0618: 'PrefabType' is obsolete: 'PrefabType no longer tells everything about Prefab instance.'

Mono build always crashes with high stripping enabled

Hello

I'm experiencing a problem with the serializer when using a mono build. When serializing with certain settings applied, the game will always outright just crash. No logs or anything, the window just closes.

This issue only happens on mono builds with high stripping enabled, even with an AOT generated dll. IL2CPP works fine, which is honestly surprising.

After a lot of Debug.Log lines placed all over the code, I've tracked it down to line 332 in FormatterEmitter.cs. That's where the log messages stop and the game just crashes.

For now, a workaround is to either use IL2CPP or use anything lower than high stripping on mono builds.

I've also attached a minimal project that has the issue.
Odin Crash.zip

Usage outside Unity

I'm not building my game in Unity; is there a way to install and use Odin Serializer in a standard .NET Framework or .NET Core application, preferably without building the source (Ex. NuGet package)? This serializer looks very impressive!

"SerializationUtility.SerializeValue" Dictionary not valid json type

i try to Serialization class to json but "key" of dictionary is not valid json type

example

 "$rcontent": [
            {
                0, <-------------------------------------[invalid json type].
                { ... }<-------------------------------------[invalid json type]
            },
            {
               1, <-------------------------------------[invalid json type]
               { ... }<-------------------------------------[invalid json type]
            }
]

i think it must look like this

 "$rcontent": [
              {
                  "$key": 0, <-------------------------------------[valid json type]
                  "$content" : { ... }<-------------------------------------[valid json type]
              },
              {
                  "$key": 1, <-------------------------------------[valid json type]
                 "$content" : { ... }<-------------------------------------[valid json type]
               }
]

test code

 byte[] bytes = SerializationUtility.SerializeValue(sr, DataFormat.JSON);
        string str = System.Text.Encoding.Default.GetString(bytes);
        Debug.Log(str);

test output


{
    "$id": 0,
    "$type": "0|DatabaseManager+SROceanTest, Assembly-CSharp",
    "serializationData": {
        "$type": "1|Sirenix.Serialization.SerializationData, Sirenix.Serialization",
        "SerializedFormat": 0,
        "SerializedBytes": null,
        "ReferencedUnityObjects": null,
        "SerializedBytesString": null,
        "Prefab": null,
        "PrefabModificationsReferencedUnityObjects": null,
        "PrefabModifications": null,
        "SerializationNodes": null
    },
    "jsOceanFish": {
        "$id": 1,
        "$type": "2|System.Collections.Generic.Dictionary`2[[System.Int32, mscorlib],[JSOceanFish, Assembly-CSharp]], mscorlib",
        "comparer": {
            "$id": 2,
            "$type": "3|System.Collections.Generic.GenericEqualityComparer`1[[System.Int32, mscorlib]], mscorlib"
        },
        "$rlength": 3,
        "$rcontent": [
            {
                0, <-------------------------------------[invalid json type]
                {
                    "$id": 3,
                    "$type": "4|JSOceanFish, Assembly-CSharp",
                    "sNameTH": "name 0",
                    "sNameEN": null,
                    "iIDFish": 0,
                    "sThumbnail": null,
                    "sDescription": null,
                    "sImageList": {
                        "$id": 4,
                        "$type": "5|System.Collections.Generic.List`1[[System.String, mscorlib]], mscorlib",
                        "$rlength": 3,
                        "$rcontent": [
                            "image 0",
                            "image 1",
                            "image 2"
                        ]
                    }
                }
            },
            {
                1,<-------------------------------------[invalid json type]
                {
                    "$id": 5,
                    "$type": 4,
                    "sNameTH": "name 1",
                    "sNameEN": null,
                    "iIDFish": 1,
                    "sThumbnail": null,
                    "sDescription": null,
                    "sImageList": {
                        "$id": 6,
                        "$type": 5,
                        "$rlength": 3,
                        "$rcontent": [
                            "image 0",
                            "image 1",
                            "image 2"
                        ]
                    }
                }
            },
            {
                2, <-------------------------------------[invalid json type]
                {
                    "$id": 7,
                    "$type": 4,
                    "sNameTH": "name 2",
                    "sNameEN": null,
                    "iIDFish": 2,
                    "sThumbnail": null,
                    "sDescription": null,
                    "sImageList": {
                        "$id": 8,
                        "$type": 5,
                        "$rlength": 3,
                        "$rcontent": [
                            "image 0",
                            "image 1",
                            "image 2"
                        ]
                    }
                }
            }
        ]
    }
}   

Serializing GameObjects?

I'm trying to compose a GameObject at runtime and then serialize it, but am failing. Is this not supported?

Here's a simple repro; attach this to an empty game object in a scene and run it:

public class TestComponent : SerializedMonoBehaviour
{
    public int testValue = 100;
}

public class TestScript : MonoBehaviour
{
    void Start()
    {
        var go = new GameObject();
        go.AddComponent<TestComponent>();

        byte[] bytes = SerializationUtility.SerializeValue(go, DataFormat.JSON);
        File.WriteAllBytes("testOutput", bytes);

        /* Contents of 'testOutput' file after running the above:
        {
            "$id": 0,
            "$type": "0|UnityEngine.GameObject, UnityEngine.CoreModule"
        }
        */
    }
}

I was expecting to see 'TestComponent' in the testOutput file. I just purchased OdinInspector so am still trying to orient myself on what is/isn't expected to work wrt persisting composed GOs.

Thanks,
Jeff

Serialization of built-in Unity ScriptableObject: TimelineAsset

Hello,
I'm trying to serialize a TimelineAsset, which is a built-in ScriptableObject that stores Timeline related data. The TimelineAsset stores multiple references to other ScriptableObjects such as TrackAssets and TimelineClips.
Is there a way to serialize a TimelineAsset and all its children assets using Odin serializer ?

  • I can't make TimelineAsset to inherit from SerializedScriptableObject since it's a built-in class.
  • I have noticed TimelineAsset already inherits from the ISerializationCallbackReceiver interface.

I already tried to serialize it by using:

byte[] lData = SerializationUtility.SerializeValue<TimelineAsset>(mTimeline, DataFormat.JSON);

but this gives me several warnings like this one:

A formatter has been created for the UnityEngine.Object type TimelineAsset - this is *strongly* discouraged.
Unity should be allowed to handle serialization and deserialization of its own weird objects.
Remember to serialize with a UnityReferenceResolver as the external index reference resolver in the serialization context.

I must admit I don't really understand what the SerializationContext and DeserializationContext are used for.

If I try to deserialize the previously serialized data using:

byte[] lData = File.ReadAllBytes(lPath);
mTimeline = SerializationUtility.DeserializeValue<TimelineAsset>(lData, DataFormat.JSON);

Then the object returned by DeserializeValue() is null.

Any help is much appreciated !

unity 2019.3 missing Unity.Networking

Assembly 'Assets/Plugins/Sirenix/Odin Serializer/EditorOnly/OdinSerializer.dll' will not be loaded due to errors:
Unable to resolve reference 'UnityEngine.Networking'. Is the assembly missing or incompatible with the current platform?
Reference validation can be disabled in the Plugin Inspector.

Using 2019.3.0b3 on Linux (Ubuntu)

Does not serialize values of Vector2Int

Raised this on the Discord, but thought it might be a good idea to submit an issue as well.
I'm trying to serialize a Vector2Int, but it seems to only be recording the type of the Vector2Int, and not the values.
Vector2 types are serialised properly; with their values intact.

Here is what I have marked on my Vector2Int (note that changing it to [SerializeField] does not make a difference).
21-01-29-11 21

And this is the result.
21-01-29-11 19

The same thing on a Vector2:
21-01-29-11 26
21-01-29-11 26 (2)

EDIT: It looks like I was somehow missing VectorIntFormatters.cs. Getting this file from the Discord solved this issue.

Keeping default Unity behavior of instantiating fields when they are null instead of serialization and keeping null?

I am looking into using Odin Serializer to greatly simplify serialization of some data in our game. (Mainly the data for the battle system in a super flexible JRPG engine, loads of skills and configurables like procs, effects, triggers, etc.)

The most infuriating pattern I've noticed over and over again that is very irritating is a workaround I use due to missing support of polymorphism by default in Unity. I use an enum and pack all the fields of every 'type' in there, and there's a weird switch statement somewhere. We use VFW for advanced drawers and attributes (unfortunately perhaps we should have been early adopters of Odin it looks like, as Odin was just coming out at the time.) so we have a visibility attribute which grabs the enum field and changes the visibility based on the value and stuff. Basically it makes it a pain to add new stuff, and it's neither maintainable or readable. The fact that it's everywhere makes it worse, and even more-so when there's multiple layers of enums in there. On top of that, the naming of variables is insane.

So I got Odin Serializer and so far it seems to work perfectly fine and I was able to write a much more sane configuration setup that allows for a clean hierarchy and structure, but the only hiccup is that it seems to leave values at null, whereas the default serialization in Unity will instantiate. Any way around this?

linux errors when open project (install/setup)

tried code and get warnings about 3 versions of same function? deleted 2 to test and get other error idk? should this work from Linux too idk thanks

what is the process? i am supposed to load that sceneButtons and build a debug dll and generate a unity package and copy that to my project?

sorry idk thanks

PrecompiledAssemblyException: Multiple precompiled assemblies with the same name OdinSerializer.dll included for the current platform. Only one assembly with the same name is allowed per platform. Assembly path: {0}
UnityEditor.Scripting.ScriptCompilation.EditorBuildRules.CreateTargetAssemblies (System.Collections.Generic.IEnumerable1[T] customScriptAssemblies, System.Collections.Generic.IEnumerable1[T] precompiledAssemblies) (at /home/builduser/buildslave/unity/build/Editor/Mono/Scripting/ScriptCompilation/EditorBuildRules.cs:251)
UnityEditor.Scripting.ScriptCompilation.EditorCompilation.UpdateCustomTargetAssemblies () (at /home/builduser/buildslave/unity/build/Editor/Mono/Scripting/ScriptCompilation/EditorCompilation.cs:701)
UnityEditor.Scripting.ScriptCompilation.EditorCompilation.SetAllCustomScriptAssemblyJsonContents (System.String[] paths, System.String[] contents, System.String[] guids) (at /home/builduser/buildslave/unity/build/Editor/Mono/Scripting/ScriptCompilation/EditorCompilation.cs:1011)
UnityEditor.Scripting.ScriptCompilation.EditorCompilationInterface.SetAllCustomScriptAssemblyJsonContents (System.String[] allAssemblyJsonPaths, System.String[] allAssemblyJsonContents, System.String[] guids) (at /home/builduser/buildslave/unity/build/Editor/Mono/Scripting/ScriptCompilation/EditorCompilationInterface.cs:241)

i have the store bought one too and that seems to work without errors but i only wanted the serialize to be distributable

References lost with ScriptedImporters on initial project startup

I have an issue with ScriptedImporters where references to the assets created by the importer will all be lost upon initial launch o the editor.

The references can be restored by forcing an assembly reload (e.g. by editing the code) or by editing the yaml directly so that Unity sees a change in it. (any change, even adding an invalid symbol and removing it will fix it) Right Click -> Reimport on the asset does not restore references however.

Nothing looks out of the ordinary in the asset file. From what I can remember, I think I've only seen this only occurs with fields serialized by Odin Serializer. However when I created some scriptableobjects for testing, I couldn't reproduce it. Someone else experienced this but they didn't have any solution.

	[ScriptedImporter(1, "lua")]
	public class LuaAssetImporter : ScriptedImporter
	{
		public override void OnImportAsset(AssetImportContext ctx)
		{
			if (ctx == null) return;

			LuaAsset asset = AssetDatabase.LoadAssetAtPath<LuaAsset>(ctx.assetPath);
			if (asset == null)
			{
				asset           = ScriptableObject.CreateInstance<LuaAsset>();
				asset.functions = new List<string>();

				ctx.AddObjectToAsset("main obj", asset);
				ctx.SetMainObject(asset);
			}

			asset.Path = ctx.assetPath;
			asset.functions.Clear();

			asset.hideFlags     = HideFlags.None;
			asset.ErrorMessage  = "";
			asset.ErrorOnImport = false;

			asset.UpdateText(File.ReadAllText(ctx.assetPath));

			// PopulateInfo(asset);
		}

RefreshAssemblyImportSettings returns exception

When downloading a standalone unity package from your page, and extracting it to Unity. The following error occurs after pressing RefreshAssemblyImportSettings

NullReferenceException: Object reference not set to an instance of an object
OdinSerializer.Utilities.Editor.OdinAssemblyImportSettingsUtility.ApplyImportSettings (System.String assemblyFilePath, System.Boolean includeInBuild, System.Boolean includeInEditor) (at Assets/OdinSerializer/Config/AssemblyBuildInfo.cs:137)
OdinSerializer.Utilities.Editor.OdinAssemblyImportSettingsUtility.ApplyImportSettings (System.String assemblyFilePath, OdinSerializer.Utilities.Editor.AssemblyImportSettings importSettings) (at Assets/OdinSerializer/Config/AssemblyBuildInfo.cs:129)
OdinSerializer.Utilities.Editor.AOTImportSettingsConfig.Apply () (at Assets/OdinSerializer/Config/AssemblyBuildInfo.cs:186)
OdinSerializer.Utilities.Editor.OdinSerializationBuiltSettingsConfig.RefreshAssemblyImportSettings () (at Assets/OdinSerializer/Config/AssemblyBuildInfo.cs:74)

var importer = (PluginImporter)AssetImporter.GetAtPath(assemblyFilePath); = null
assemblyPath = Assets/Plugins/Sirenix/Assemblies/NoEmitAndNoEditor/Sirenix.Serialization.dll do not exists after extraction of the UnityPackage.

image
In the UnityPackage there is no file that would match this path.

Unity: 2020.1.3f1
Target: WebGL (AOT)

Changing Polymorphic class list order and hiding members

Hello
The asset is great, im just starting to get some value out of it!
But one thing thats bothering me right now is Polymorphic class lists, they cant be reordered..
image
Also I want to hide the one starting with "_" from the list
(I have the value above from before I knew Odin could be setting them from a list like that, its a enum that just Validates)

Data mismatch error

Hello I'm trying to export a class from one unity project as unity which works fine but can't import it to another by de-serializing.
Things inside the class return null.
But when I try the same thing in the exporting project it seems to be working.

Can you please help me to resolve this issue ?

Thanks

(AOT) No serializer for C# struct (readonly or not) is pre-generated

Because my project uses structs and readonly structs heavily, so I have made a test (WebGL build) to see if OdinSerializer can work on them. However, there is no serializer for struct of any kind is pre-generated.

The test struct:

[Serializable]
public readonly struct MyData
{
    public readonly int Id;
    public readonly string Name;
    public readonly Action OnDidSomething;

    public MyData(int id, string name, Action onDidSomething)
    {
        this.Id = id;
        this.Name = name;
        this.OnDidSomething = onDidSomething;
    }
}

The result is a little unexpected, since there is no such problem with classes. I've made another test with OdinInspector 2.1.1, the problem is the same, and I have to manually input MyData into the "Support Serialized Types" list.

JsonTextReader performance suggestion - Use Ordinal string comparison instead of InvariantCulture

Hi,

I was able to make some meaningful performance improvements in deserializing large json files by changing JsonTextReader.cs to use the Ordinal string comparer instead of using InvariantCulture.
As far as I am aware, this change should not break the code for any device with any culture since the code is already explicitly using InvariantCulture. Given the strings we are checking for are all simple hard-coded strings with English characters and a few symbols ($, {, }, [, ]) there should be no difference in the results of an Ordinal or InvariantCulture equality comparison.

Please advise if there is indeed a case where this could potentially break something

Abstract classes not serialized correctly on AOT Build

Unity version: 2020.1.7f1

Odin: 3.0.1.0

Windows 10.

I’m using SerializationUtility.SerializeValue to save the state of an object so I can retrieve it later, it does work fine in editor but does not work in IL2CPP builds.

Relevant bits of code:

SerializableEntity.cs

public class SerializableEntity : MonoBehaviour
{
        Dictionary<string, EntityParameter> _parametersDict = new Dictionary<string, EntityParameter>();

        public virtual byte[] SerializeParameters()
        {
            Assert.IsNotNull(_parametersDict);

            var paremters = _parametersDict.Values.ToArray();
            var serialized = SerializationUtility.SerializeValue<EntityParameter[]>(paremters, DataFormat.JSON);

            Debug.Log("Serialize " + name + " " + paremters.Length);
            foreach (var item in paremters)
            {
                Debug.Log(item.Name);
            }
            Debug.Log(System.Text.Encoding.UTF8.GetString(serialized));

            return serialized;
        }
    }

EntityParemeter.cs

[Serializable]
  public abstract class EntityParameter
  {
    public event Action OnChanged;

    public EntityParameter()
    {
        
    }

    protected void FireOnChanged()
    {
      OnChanged?.Invoke();
    }

    [SerializeField]
    private string _name;

    public string Name
    {
      get => _name;
    }

    [SerializeField]
    private string _label = string.Empty;

    public string Label
    {
      get => _label != string.Empty ? _label : _name;
    }

    public abstract object Value
    {
      get; set;
    }

    public EntityParameter(string name, string label = null)
    {
      _name = name;
      _label = label ?? string.Empty;
    }
  }

BoolParameter.cs

  [Serializable]
  public class BoolParameter : EntityParameter
  {
    [SerializeField]
    private bool _value;

    public override object Value
    {
      get => _value;
      set
      {
        if (value.GetType() != typeof(bool)) return;
        if (value.Equals(_value)) return;
        _value = (bool)value;
        FireOnChanged();
      }
    }

    public BoolParameter(string name, bool value, string label = null) : base(name, label)
    {
      _value = value;
    }
  }

AOTPreprocessor.cs

public class AOTPreprocessor  : IPreprocessBuildWithReport
{
    public int callbackOrder => 0;

    public void OnPreprocessBuild(BuildReport report)
    {
        List<System.Type> supportedTypes;
        if (AOTSupportUtilities.ScanProjectForSerializedTypes(out supportedTypes))
        {
            supportedTypes.Add(typeof(EntityParameter));
            supportedTypes.Add(typeof(BoolParameter));
            supportedTypes.Add(typeof(EntityParameter[]));
            supportedTypes.Add(typeof(int));
            supportedTypes.Add(typeof(float));
            supportedTypes.Add(typeof(string));
            supportedTypes.Add(typeof(bool));
            supportedTypes.Add(typeof(Vector2));
            supportedTypes.Add(typeof(Vector3));
            AOTSupportUtilities.GenerateDLL(Application.dataPath + "/Plugins/", "GeneratedAOT", supportedTypes);
            Debug.Log("generate AOT");
            Debug.Log(Application.dataPath + "/Plugins/");
        }
    }

I serialized it to JSON so I can see what is happening and in the editor, the log is this:

Serialize TerroristEditor(Clone) 1

_isFacingRight

{
"$id": 0,
"$type": "0|MRChip.LevelManager.EntityParameter[], Plugins",
"$rlength": 1,
"$rcontent": [{"$id": 1,"$type": "1|MRChip.LevelManager.BoolParameter, Plugins","_name": "_isFacingRight","_label": "Is Facing Right","_value": true}]
}

The exact same scene, with the exact same object in the IL2CPP build, results is this:

Serialize TerroristEditor(Clone) 1

_isFacingRight
{
    "$id": 0,
    "$type": "0|MRChip.LevelManager.EntityParameter[], Plugins"
}

The parameter ( “_isFacingRight”) is in the object, but it is not present on the serialization.

How to deserialize json string to array data ?

How to deserialize json string to array data ?

[{"name": "J - Guide", "author": "H ft. Cb", "trial": "", "difficulty": "1", "json": "j-guide", "id": "50000"}, {"name": "J - Guide Ⅱ", "author": "Hoiyip", "trial": "", "difficulty": "1", "json": "j-guide-ii", "id": "59000"}]

and this is my model

[Serializable]
    public class SongLibItemModel
    {
        public string name;
        public string author;
        public string trial;
        public string difficulty;
        public string json;
        public string id;
    }

I try to run these

SerializationUtility.DeserializeValue<List<SongLibItemModel>>(libTextAsset.bytes, DataFormat.JSON);

but it returns null.

[2019.1] Error on installing

Hey, when I install the latest version from downloads it gives errors in 2019.1.0f2:
Assembly 'Assets/Plugins/Sirenix/Odin Serializer/EditorOnly/OdinSerializer.dll' will not be loaded due to errors:
Unable to resolve reference 'UnityEngine.Networking'. Is the assembly missing or incompatible with the current platform?
Reference validation can be disabled in the Plugin Inspector.

I have looked in the package manager and can't find anything related to networking so have I missed something?

Should Guid's be serialized as strings?

Hey there, I noticed that a guid I have in my serialized object causes several editors (VS 2022, VS Code, Notepad++) to whine about an invalid character sequence.
image

Is there an option somewhere to force it to quote the guid value or serialize as string by default?

Note, I have no problem deserializing these with odin, but I plan to post this to an aspnet core api and I'm not sure yet if that will be able to parse a guid like this.
[edit - as a workaround i can just use string in my class and use guid.ToString() when creating it]

Alternative untyped deserializer?

Is it possible to make an untyped deserializer?
(Deserialize to some weakly typed tree, or just fire callbacks like emitString(), emitObjectBegin() etc.)
It seems that odin-serializer's binary format stores sufficient data to restore a JSON-like tree with type name.
However the deserialzer is strongly dependent on runtime type and cannot be used if type is unavailable.

What I want is to export game's serialized data for modding, in offline tools.
(Export to untyped format like Json.NET, so that it is easy to format/reuse in other types)

The binary format seems clear, and BinaryDataReader can be reused.
But the the state machine of deserializer + formatter seems to be tricky, I am unclear how to replicate it.

SceneView.onSceneGUIDelegate obsolete

In the build project's SceneViewBuildButton, the SceneView.onSceneGUIDelegate callback registration is obsolete (since I believe 2019.1).

To eliminate the warning it should be wrapped around:

        [InitializeOnLoadMethod]
        private static void Init()
        {
#if UNITY_2019_1_OR_NEWER
            SceneView.duringSceneGui += DrawButtons;
#else
            SceneView.onSceneGUIDelegate += DrawButtons;
#endif
        }

Issue when serializing abstract classes as private members.

Hi!

I was trying to use Odin Inspector and found that one of our classes was not serializing at all the it was rendered by Odin, but it was working properly when excluded.

After some debugging, I found that Odin was crashing on MemberInfoExtensions.GetAttributes due to a private member which is an abstract class, an actual native c# class. No dependencies with Unity.

I manage to fix the issue by swapping Odin to Sources and modifying the source code as provided in the path file. (renamed to txt as requested by GitHub)

MemberInfoExtensions-patch.diff.txt

If would be great If you do not find any incompatibilities with it and could integrate the fix in the binary version.

Thanks for your time!
Jose

Is it's possible to use opensource version of Odin serializer in IL2CPP?

Hi. I was trying to use opensource version of Odin serializer (downloaded unitypackage from the site after registration), but it looks like I can not use it without Unity editor tools. Serialization is not working in IL2CPP build with the error message:
No AOT serializer was pre-generated for the type 'Components.GameScene'. Please use Odin's AOT generation feature to generate an AOT dll before building, and ensure that 'Components.GameScene' is in the list of supported types after a scan. If it is not, please report an issue and add it to the list manually.
Components.GameScene is declared as follows:
[Serializable] public enum GameScene { Menu = 0, Flying = 1, Platform = 2 }
I can not found that list in the editor: I have only "refresh assembly import settings" in the "Tools-> Odin Serializer" menu. I have to install Odin inspector to be able to edit that supported types list?
I also created prebuild script to generate .dll:
`#if UNITY_EDITOR
using OdinSerializer.Editor;
using UnityEditor.Build;
using UnityEditor.Build.Reporting;
using UnityEngine;

namespace Editor
{
public class OdinFormatterPreprocessor : IPreprocessBuildWithReport
{
public int callbackOrder { get; }
public void OnPreprocessBuild(BuildReport report)
{
if (AOTSupportUtilities.ScanProjectForSerializedTypes(out var supported))
{
AOTSupportUtilities.GenerateDLL(Application.dataPath + "/Plugins/", "odinAssembly", supported);
}
}
}
}
#endif`

But nothing changed. I have to install Odin inspector in order to be able to use serializer with AOT, or there are some other setup is required? Can't find the appropriate documentation

Missing Namespace

Opening up a non-modified version in Unity throws this error :
Assets\Plugins\Sirenix\Odin Serializer\OdinBuildAutomation.cs(4,26): error CS0234: The type or namespace name 'Editor' does not exist in the namespace 'OdinSerializer' (are you missing an assembly reference?)

Is this expected ?

Can't import package due to error

When I try to import the downloaded package from the odin serializer site, I get this error:

Failed to import package with error: Couldn't decompress package

Tried searching but couldn't find anything conclusive. I'm using the absolute latest version of Unity at the time of this writing (2019.3.0f1), maybe that's the reason

Differences between this repository and the asset store version

Are there differences between this repository and the asset store version? Why is the asset store version priced 50$ when this repository is also available? The Apache-2 license also seems not to restrict anything in particular to explain the difference.

Cannot Open "Build" folder in Unity 2019.1

Hello.

First off, I am assuming that I am having this problem because Unity 2019.1 was JUST released. However, I figured I would open an issue just so you guys can see.

When I download odin-serializer and open the project, I cannot open it properly in Unity 2019.1. This does work in Unity 2018.3, however.

Here is what I mean.

  1. Open Unity Hub
  2. Click Open
  3. Navigate to the odin-serializer folder and double-click the Build folder
  4. Wait for Unity to load
  5. Once Unity is loaded, no scene view buttons are present.

This is an issue since the README.md says that the recommended way to build the project is through Unity.

Any ideas on how I could fix this?

Thanks,
Kyle

[Questions] Serialization in edit mode

Writing editor tools it's always so irritating to find out that a object resets on reload(open project/code recompile etc) jut because it's a dictionary or a list with custom classes for example. So I wander If this tool can be used to solve that problem, serialising non-compatable types in edit mode or does it only work for saving data in play mode? Also if it's possible can you nudge me in the right direction? Thanks.

Does SerializationPolicies.Unity Serializes Auto-Properties?

/// Public fields and fields or auto-properties marked with <see cref="SerializeField"/> or <see cref="OdinSerializeAttribute"/> and not marked with <see cref="NonSerializedAttribute"/> are serialized.
/// <para />
/// There are two exceptions: all fields in tuples, as well as in private nested types marked as compiler generated (e.g. lambda capture classes) are also serialized.
/// </summary>
public static ISerializationPolicy Unity

However,

public class Sample : MonoBehaviour
{
	public class Foo
	{
		public int Bar { get; set; }
	}
	void Start()
	{
		Debug.Log(Encoding.UTF8.GetString(SerializationUtility.SerializeValue(new Foo(), DataFormat.JSON)));
	}
}

returns:

{
	"$id": 0,
	"$type": "0|Sample+Foo, Assembly-CSharp"
}

So then i'm not sure which one is correct.

Gradient Formatter Error

InvalidOperationException: Was not in array when exiting array.
Ludiq.OdinSerializer.BaseDataReaderWriter.PopArray () (at C:/Users/lazlo/Projects/LudiqOdinSerializer/OdinSerializer/Core/DataReaderWriters/BaseDataWriter.cs:65)
Ludiq.OdinSerializer.BinaryDataWriter.EndArrayNode () (at C:/Users/lazlo/Projects/LudiqOdinSerializer/OdinSerializer/Core/DataReaderWriters/Binary/BinaryDataWriter.cs:387)
Ludiq.OdinSerializer.DerivedDictionaryFormatter`3[TDictionary,TKey,TValue].SerializeImplementation (TDictionary& value, Ludiq.OdinSerializer.IDataWriter writer) (at <01bb2e6357a34a49bb753986695fa221>:0)
Ludiq.OdinSerializer.BaseFormatter`1[T].Serialize (T value, Ludiq.OdinSerializer.IDataWriter writer) (at C:/Users/lazlo/Projects/LudiqOdinSerializer/OdinSerializer/Core/Formatters/DelegateFormatter.cs:330)
Rethrow as SerializationAbortException: An exception of type InvalidOperationException occurred during serialization or deserialization.
Ludiq.OdinSerializer.ComplexTypeSerializer`1[T].WriteValue (System.String name, T value, Ludiq.OdinSerializer.IDataWriter writer) (at C:/Users/lazlo/Projects/LudiqOdinSerializer/OdinSerializer/Unity Integration/Formatters/ColorFormatter.cs:33)
Ludiq.OdinSerializer.Serializer`1[T].WriteValue (T value, Ludiq.OdinSerializer.IDataWriter writer) (at C:/Users/lazlo/Projects/LudiqOdinSerializer/OdinSerializer/Unity Integration/Formatters/GradientFormatter.cs:55)
Ludiq.OdinSerializer.SerializationUtility.SerializeValue[T] (T value, Ludiq.OdinSerializer.IDataWriter writer, System.Collections.Generic.List`1[UnityEngine.Object]& unityObjects) (at C:/Users/lazlo/Projects/LudiqOdinSerializer/OdinSerializer/Utilities/Extensions/TypeExtensions.cs:1471)
Ludiq.OdinSerializer.SerializationUtility.SerializeValue[T] (T value, System.IO.Stream stream, Ludiq.OdinSerializer.DataFormat format, System.Collections.Generic.List`1[UnityEngine.Object]& unityObjects, Ludiq.OdinSerializer.SerializationContext context) (at C:/Users/lazlo/Projects/LudiqOdinSerializer/OdinSerializer/Utilities/Extensions/TypeExtensions.cs:1598)
Ludiq.OdinSerializer.SerializationUtility.SerializeValue[T] (T value, Ludiq.OdinSerializer.DataFormat format, System.Collections.Generic.List`1[UnityEngine.Object]& unityObjects, Ludiq.OdinSerializer.SerializationContext context) (at C:/Users/lazlo/Projects/LudiqOdinSerializer/OdinSerializer/Utilities/Extensions/TypeExtensions.cs:1824)
Ludiq.Serialization.OdinSerialize[T] (T value, Ludiq.OdinSerializer.SerializationData& data, Ludiq.OdinSerializer.DataFormat format) (at Assets/Ludiq/Ludiq.Core/Runtime/Serialization/Serialization.cs:358)
Rethrow as SerializationException: Serialization of 'Ludiq.Bolt.SetMember' failed.
Ludiq.Serialization.OdinSerialize[T] (T value, Ludiq.OdinSerializer.SerializationData& data, Ludiq.OdinSerializer.DataFormat format) (at Assets/Ludiq/Ludiq.Core/Runtime/Serialization/Serialization.cs:389)
Ludiq.Serialization.OdinSerialize[T] (T value, Ludiq.OdinSerializer.DataFormat format) (at Assets/Ludiq/Ludiq.Core/Runtime/Serialization/Serialization.cs:339)
Ludiq.Bolt.UnitOption`1[TUnit].Serialize () (at Assets/Ludiq/Bolt.Flow/Editor/Options/UnitOption.cs:161)
Ludiq.Bolt.MemberUnitOption`1[TMemberUnit].Serialize () (at Assets/Ludiq/Bolt.Flow/Editor/Framework/Codebase/MemberUnitOption.cs:125)
Ludiq.Bolt.UnitOptionsExtractor+<>c.<ExtractFull>b__12_1 (Ludiq.Bolt.IUnitOption option) (at Assets/Ludiq/Bolt.Flow/Editor/Options/UnitOptionsExtractor.cs:85)
Ludiq.TaskLinq+<>c__DisplayClass4_0`2[TSource,TResult].<SelectTask>b__0 (TSource item) (at Assets/Ludiq/Ludiq.Core/Editor/Tasks/TaskLinq.cs:101)
Ludiq.TaskLinq+<>c__DisplayClass3_2`2[TSource,TResult].<SelectManyTask>b__1 (TSource item) (at Assets/Ludiq/Ludiq.Core/Editor/Tasks/TaskLinq.cs:71)
System.Threading.Tasks.Parallel+<>c__DisplayClass42_0`2[TSource,TLocal].<PartitionerForEachWorker>b__1 () (at <d7ac571ca2d04b2f981d0d886fa067cf>:0)
System.Threading.Tasks.Task.InnerInvoke () (at <d7ac571ca2d04b2f981d0d886fa067cf>:0)
System.Threading.Tasks.Task.InnerInvokeWithArg (System.Threading.Tasks.Task childTask) (at <d7ac571ca2d04b2f981d0d886fa067cf>:0)
System.Threading.Tasks.Task+<>c__DisplayClass178_0.<ExecuteSelfReplicating>b__0 (System.Object <p0>) (at <d7ac571ca2d04b2f981d0d886fa067cf>:0)
Rethrow as AggregateException: One or more errors occurred.
System.Threading.Tasks.Task.ThrowIfExceptional (System.Boolean includeTaskCanceledExceptions) (at <d7ac571ca2d04b2f981d0d886fa067cf>:0)
System.Threading.Tasks.Task.Wait (System.Int32 millisecondsTimeout, System.Threading.CancellationToken cancellationToken) (at <d7ac571ca2d04b2f981d0d886fa067cf>:0)
System.Threading.Tasks.Task.Wait () (at <d7ac571ca2d04b2f981d0d886fa067cf>:0)
System.Threading.Tasks.Parallel.PartitionerForEachWorker[TSource,TLocal] (System.Collections.Concurrent.Partitioner`1[TSource] source, System.Threading.Tasks.ParallelOptions parallelOptions, System.Action`1[T] simpleBody, System.Action`2[T1,T2] bodyWithState, System.Action`3[T1,T2,T3] bodyWithStateAndIndex, System.Func`4[T1,T2,T3,TResult] bodyWithStateAndLocal, System.Func`5[T1,T2,T3,T4,TResult] bodyWithEverything, System.Func`1[TResult] localInit, System.Action`1[T] localFinally) (at <d7ac571ca2d04b2f981d0d886fa067cf>:0)
System.Threading.Tasks.Parallel.ForEach[TSource] (System.Collections.Concurrent.Partitioner`1[TSource] source, System.Threading.Tasks.ParallelOptions parallelOptions, System.Action`1[T] body) (at <d7ac571ca2d04b2f981d0d886fa067cf>:0)
Ludiq.TaskLinq+<>c__DisplayClass3_0`2[TSource,TResult].<SelectManyTask>b__0 (Ludiq.Task task) (at Assets/Ludiq/Ludiq.Core/Editor/Tasks/TaskLinq.cs:67)
Ludiq.Task.Run () (at Assets/Ludiq/Ludiq.Core/Editor/Tasks/Task.cs:65)
Ludiq.WindowTaskRunner.RunSynchronous (Ludiq.Task task) (at Assets/Ludiq/Ludiq.Core/Editor/Tasks/Runners/WindowTaskRunner.cs:61)
UnityEngine.Debug:LogException(Exception)
Ludiq.WindowTaskRunner:RunSynchronous(Task) (at Assets/Ludiq/Ludiq.Core/Editor/Tasks/Runners/WindowTaskRunner.cs:67)
Ludiq.WindowTaskRunner:Run(Task) (at Assets/Ludiq/Ludiq.Core/Editor/Tasks/Runners/WindowTaskRunner.cs:44)
Ludiq.Task:Run(String, Int32, Action`1) (at Assets/Ludiq/Ludiq.Core/Editor/Tasks/Task.cs:194)
Ludiq.TaskLinq:SelectManyTask(IEnumerable`1, String, Boolean, Func`2, Func`2) (at Assets/Ludiq/Ludiq.Core/Editor/Tasks/TaskLinq.cs:61)
Ludiq.TaskLinq:SelectTask(IEnumerable`1, String, Boolean, Func`2, Func`2) (at Assets/Ludiq/Ludiq.Core/Editor/Tasks/TaskLinq.cs:101)
Ludiq.Bolt.<>c__DisplayClass12_0:<ExtractFull>b__0(Task) (at Assets/Ludiq/Bolt.Flow/Editor/Options/UnitOptionsExtractor.cs:83)
Ludiq.Task:Run() (at Assets/Ludiq/Ludiq.Core/Editor/Tasks/Task.cs:65)
Ludiq.WindowTaskRunner:RunSynchronous(Task) (at Assets/Ludiq/Ludiq.Core/Editor/Tasks/Runners/WindowTaskRunner.cs:61)
Ludiq.WindowTaskRunner:Run(Task) (at Assets/Ludiq/Ludiq.Core/Editor/Tasks/Runners/WindowTaskRunner.cs:44)
Ludiq.Task:Run(String, Int32, Action`1) (at Assets/Ludiq/Ludiq.Core/Editor/Tasks/Task.cs:194)
Ludiq.Bolt.UnitOptionsExtractor:ExtractFull(ExtractionConfiguration) (at Assets/Ludiq/Bolt.Flow/Editor/Options/UnitOptionsExtractor.cs:67)
Ludiq.Bolt.UnitOptionsExtractor:Extract(ExtractionConfiguration) (at Assets/Ludiq/Bolt.Flow/Editor/Options/UnitOptionsExtractor.cs:53)
Ludiq.Bolt.<>c__DisplayClass19_0:<Extract>b__0(Task) (at Assets/Ludiq/Bolt.Core/Editor/Extraction/Extraction.cs:88)
Ludiq.Task:Run() (at Assets/Ludiq/Ludiq.Core/Editor/Tasks/Task.cs:65)
Ludiq.WindowTaskRunner:RunSynchronous(Task) (at Assets/Ludiq/Ludiq.Core/Editor/Tasks/Runners/WindowTaskRunner.cs:61)
Ludiq.<>c__DisplayClass10_0:<Run>b__0() (at Assets/Ludiq/Ludiq.Core/Editor/Tasks/Runners/WindowTaskRunner.cs:33)
System.Threading.ThreadHelper:ThreadStart()

SerializationUtility.Serialize is not a valid function

Hi devs,

In your development readme you quote an example using "SerializationUtility.Serialize(data)"

This function does not exist in the released package. You can call the individual functions to serialize but this omission/error is very confusing if you are just trying to just "plug and play" and follow your examples.

Nodes data formatting not compatible with Addressables/SBP builds

While using Editor Serialization Format: Nodes, Odin-serialized data is lost on building the Player Content data in Addressables. But when switching to Binary or JSON for editor, it works as expected.

It seems like the serializer simply doesn't detect SBP builds to know to use the build serialization format instead.

From a quick and naive test, it seems like checking for typeof(UnityEditor.Build.Pipeline.ContentPipeline) (along with the old build pipeline) at UnitySerializationUtility:424 does the trick. But I only tested it with Addressable's 'Build Player Content' option with a BundledAssetGroupSchema.

Simple SerializedScriptableObject ArgumentNullException: Value cannot be null. on DeserializeValue

Hello team,

in Unity 2018.3.0f5 when trying to deserialize a simple SerializedScriptableObject I get a NullException and the object return null.

I've created a simple code that reproduce the error.

`
using System.IO;
using test.OdinSerializer;
using UnityEngine;
using Debug = UnityEngine.Debug;

[CreateAssetMenu(fileName = "PlayerData", menuName = "_Config/DataCentral/PlayerData", order = 1)]
public class PlayerData : SerializedScriptableObject
{
public string PlayerName;
}

public class Save : MonoBehaviour
{
private PlayerData myData;
public PlayerData Template;

void Start()
{
    //instanciate based on my template
    myData = ScriptableObject.Instantiate(Template);
}

void Update()
{
    string jsonString;
    
    if (Input.GetKeyDown(KeyCode.S))
    {
        myData.PlayerName = "Bob";
        byte[] serializedData = SerializationUtility.SerializeValue<PlayerData>(myData, DataFormat.JSON);
        
        jsonString = System.Text.Encoding.UTF8.GetString(serializedData);
        File.WriteAllText("save.txt", jsonString);
    }
    
    if (Input.GetKeyDown(KeyCode.L))
    {
        byte[] jsonBytes = File.ReadAllBytes("save.txt");
        myData = SerializationUtility.DeserializeValue<PlayerData>(jsonBytes,DataFormat.JSON);
        Debug.Log("My data : " + myData); //return NULL
    }
}

}

`

Json value
{ "$id": 0, "$type": "0|PlayerData, Assembly-CSharp", "serializationData": { "$type": "1|test.OdinSerializer.SerializationData, test.OdinSerializer", "SerializedFormat": 0, "SerializedBytes": { "$id": 1, "$type": "2|System.Byte[], mscorlib", "$plength": 0, "$pcontent": [ ] }, "ReferencedUnityObjects": { "$id": 2, "$type": "3|System.Collections.Generic.List1[[UnityEngine.Object, UnityEngine.CoreModule]], mscorlib",
"$rlength": 0,
"$rcontent": [
]
},
"SerializedBytesString": "",
"Prefab": null,
"PrefabModificationsReferencedUnityObjects": {
"$id": 3,
"$type": 3,
"$rlength": 0,
"$rcontent": [
]
},
"PrefabModifications": {
"$id": 4,
"$type": "4|System.Collections.Generic.List1[[System.String, mscorlib]], mscorlib", "$rlength": 0, "$rcontent": [ ] }, "SerializationNodes": { "$id": 5, "$type": "5|System.Collections.Generic.List1[[test.OdinSerializer.SerializationNode, test.OdinSerializer]], mscorlib",
"$rlength": 0,
"$rcontent": [
]
}
},
"PlayerName": "Bob"
}`

Error:

ArgumentNullException: Value cannot be null.
Parameter name: unityObject
test.OdinSerializer.UnitySerializationUtility.DeserializeUnityObject (UnityEngine.Object unityObject, test.OdinSerializer.SerializationData& data, test.OdinSerializer.DeserializationContext context, System.Boolean isPrefabData, System.Collections.Generic.List1[T] prefabInstanceUnityObjects) (at Assets/test.OdinSerializer/Unity Integration/UnitySerializationUtility.cs:1182) test.OdinSerializer.UnitySerializationUtility.DeserializeUnityObject (UnityEngine.Object unityObject, test.OdinSerializer.SerializationData& data, test.OdinSerializer.DeserializationContext context) (at Assets/test.OdinSerializer/Unity Integration/UnitySerializationUtility.cs:1171) test.OdinSerializer.SerializedScriptableObject.UnityEngine.ISerializationCallbackReceiver.OnAfterDeserialize () (at Assets/test.OdinSerializer/Unity Integration/SerializedUnityObjects/SerializedScriptableObject.cs:36) test.OdinSerializer.BaseFormatter1[T].Deserialize (test.OdinSerializer.IDataReader reader) (at Assets/test.OdinSerializer/Core/Formatters/BaseFormatter.cs:256)
UnityEngine.Debug:LogException(Exception)
test.OdinSerializer.CustomLogger:LogException(Exception) (at Assets/test.OdinSerializer/Core/Misc/CustomLogger.cs:82)
test.OdinSerializer.DebugContext:LogException(Exception) (at Assets/test.OdinSerializer/Core/Misc/SerializationConfig.cs:252)
test.OdinSerializer.BaseFormatter1:Deserialize(IDataReader) (at Assets/test.OdinSerializer/Core/Formatters/BaseFormatter.cs:261) test.OdinSerializer.ComplexTypeSerializer1:ReadValue(IDataReader) (at Assets/test.OdinSerializer/Core/Serializers/ComplexTypeSerializer.cs:366)
test.OdinSerializer.SerializationUtility:DeserializeValue(IDataReader) (at Assets/test.OdinSerializer/Core/Misc/SerializationUtility.cs:469)
test.OdinSerializer.SerializationUtility:DeserializeValue(Stream, DataFormat, DeserializationContext) (at Assets/test.OdinSerializer/Core/Misc/SerializationUtility.cs:588)
test.OdinSerializer.SerializationUtility:DeserializeValue(Byte[], DataFormat, DeserializationContext) (at Assets/test.OdinSerializer/Core/Misc/SerializationUtility.cs:683)
Save:Update() (at Assets/Save.cs:32)

Unity Package support

Are there any plans to provide the Odin framework as a Unity Package compatible with the Package Manager?

It'd be convenient to include it in other packages, but right now that requires copying the entire asset over. That becomes problematic if other packages also uses Odin, or if the user is using the Odin Inspector.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.