Invalid entry during build, then failed deserialization at runtime

Issue #484 new
Lazlo Bonin
created an issue

When in the editor, my game runs perfectly fine. When building, I get the following error:

Encountered invalid entry while reading serialization data for Unity object of type 'Impossible.Ete.TransparentMeshRenderer'. Please report this issue at 'https://bitbucket.org/sirenix/odin-inspector/issues', and copy paste this debug message into the issue report, along with any potential actions or recent changes in the project that might have happened to cause this message to occur. If the data dump in this message is cut off, please find the editor's log file (see https://docs.unity3d.com/Manual/LogFiles.html) and copy paste the full version of this message from there.

Data dump:

Reader type: SerializationNodeDataReader
Data dump: Nodes:

- Name:     <<<< READ POSITION
  Entry: 0
  Data: 
- Name: 
  Entry: 0
  Data: 
- Name: 
  Entry: 0
  Data: 
- Name: 
  Entry: 0
  Data:
UnityEngine.Debug:LogError(Object)
Sirenix.Serialization.CustomLogger:LogError(String) (at D:/Repositories/SirenixFramework/Sirenix Solution/Sirenix.Serialization.Config/CustomLogger.cs:53)
Sirenix.Serialization.DebugContext:LogError(String) (at D:/Repositories/SirenixFramework/OdinSerializer/OdinSerializer/Core/Misc/SerializationConfig.cs:208)
Sirenix.Serialization.UnitySerializationUtility:DeserializeUnityObject(Object, IDataReader) (at D:/Repositories/SirenixFramework/OdinSerializer/OdinSerializer/Unity Integration/UnitySerializationUtility.cs:1596)
Sirenix.Serialization.UnitySerializationUtility:DeserializeUnityObject(Object, SerializationData&, DeserializationContext, Boolean, List`1) (at D:/Repositories/SirenixFramework/OdinSerializer/OdinSerializer/Unity Integration/UnitySerializationUtility.cs:1413)
Sirenix.Serialization.UnitySerializationUtility:DeserializeUnityObject(Object, SerializationData&, DeserializationContext) (at D:/Repositories/SirenixFramework/OdinSerializer/OdinSerializer/Unity Integration/UnitySerializationUtility.cs:1133)
Impossible.Ete.BaseComponent:OnAfterDeserialize() (at Assets/Scripts/Utility/BaseComponent.cs:35)
UnityEditor.BuildPlayerWindow:BuildPlayerAndRun()

I have a fairly complex project and I haven't had time to isolate this specifically, but I'm hoping you could point me in the right direction to fix it. Otherwise, I'll likely just remove Odin serialization from the project as my deadline is looming.

In the following pastes, I excluded the methods / constructors, as they're probably not relevant at all.

The class in question is defined as:

using UnityEngine;

namespace Impossible.Ete
{
    [RequireComponent(typeof(MeshFilter))]
    public sealed class TransparentMeshRenderer : TransparentRenderer
    {
        [Serialize]
        public int[] submeshes;
    }
}

Its parent, TransparentRenderer:

using UnityEngine;
using UnityEngine.Rendering;

namespace Impossible.Ete
{
    public abstract class TransparentRenderer : CustomRenderer
    {
        private static Material depthMaterial;
        private static Material normalsMaterial;
        private static Material depthCopyMaterial;
    }
}

That class's direct parent, CustomRender, does not define field or properties.

The root component class, BaseComponent, uses a custom serialization policy.

using System;
using Rewired;
using Sirenix.OdinInspector;
using Sirenix.Serialization;
using UnityEngine;
using Input = Rewired.Player;

namespace Impossible.Ete
{
    [ShowOdinSerializedPropertiesInInspector]
    [OptInSerialization]
    public class BaseComponent : MonoBehaviour, ISerializationCallbackReceiver, ISupportsPrefabSerialization, IOverridesSerializationPolicy
    {
        #region Serialization

        [SerializeField, HideInInspector, DoNotSerialize]
        private SerializationData serializationData;

        public virtual void OnAfterDeserialize()
        {
            var context = new DeserializationContext();
            context.Config.SerializationPolicy = SerializationPolicy;
            UnitySerializationUtility.DeserializeUnityObject(this, ref serializationData, context);
        }

        public virtual void OnBeforeSerialize()
        {
            var context = new SerializationContext();
            context.Config.SerializationPolicy = SerializationPolicy;
            UnitySerializationUtility.SerializeUnityObject(this, ref serializationData, true, context);
        }

        public bool OdinSerializesUnityFields => true;

        public ISerializationPolicy SerializationPolicy
        {
            get
            {
                return Ete.SerializationPolicy.instance;
            }
        }

        SerializationData ISupportsPrefabSerialization.SerializationData
        {
            get { return serializationData; }
            set { serializationData = value; }
        }

        #endregion

        public Guid guid { get; private set; }
}

The policy is defined as:

using Sirenix.Serialization;
using System.Reflection;
using Sirenix.Utilities;
using UnityEngine;
using System;

namespace Impossible.Ete
{
    public sealed class SerializationPolicy : ISerializationPolicy
    {
        public static SerializationPolicy instance { get; } = new SerializationPolicy();

        public string ID => "Ete";

        public bool AllowNonSerializableTypes => true;

        public bool ShouldSerializeMember(MemberInfo member)
        {
            if (member.IsDefined<DoNotSerializeAttribute>(true) ||
                member.IsDefined<NonSerializedAttribute>(true))
            {
                return false;
            }

            if (member.IsDefined<SerializeAttribute>(true) ||
                member.IsDefined<SerializeField>(true))
            {
                return true;
            }

            // On types we control, we generally want strict opt-in serialization
            // In those, skip anything that was note explicitly marked as serialize
            if (member.ReflectedType.IsDefined<OptInSerializationAttribute>())
            {
                return false;
            }

            // But other types, mostly Unity types, we don't control.
            // In those, serialize only public fields, like Unity would.
            if (member is FieldInfo)
            {
                var field = (FieldInfo)member;

                return field.IsPublic;
            }

            return false;
        }
    }
}

I wish I could give more data about the object that fails itself, but the error message isn't linked to an object reference, so I don't know which it is.

Comments (2)

  1. Lazlo Bonin reporter

    I managed to fix it by removing and re-adding all instances of the component across all my scenes. Not sure what exactly was causing it, but the data had been corrupted somehow.

  2. Log in to comment