public override fsResult TrySerialize(object instance, out fsData serialized, Type storageType)
        {
            var type = (Type)instance;

            serialized = new fsData(RuntimeCodebase.SerializeType(type));
            return(fsResult.Success);
        }
Exemplo n.º 2
0
        private fsResult InternalSerialize_2_Inheritance(Type storageType, Type overrideConverterType, object instance, out fsData data)
        {
            // Serialize the actual object with the field type being the same as
            // the object type so that we won't go into an infinite loop.
            var serializeResult = InternalSerialize_3_ProcessVersioning(overrideConverterType, instance, out data);

            if (serializeResult.Failed)
            {
                return(serializeResult);
            }

            // Do we need to add type information? If the field type and the
            // instance type are different then we will not be able to recover
            // the correct instance type from the field type when we deserialize
            // the object.
            //
            // Note: We allow converters to request that we do *not* add type
            //       information.
            if (storageType != instance.GetType() &&
                GetConverter(storageType, overrideConverterType).RequestInheritanceSupport(storageType))
            {
                var instanceType = instance.GetType();

                // LAZLO / LUDIQ
                // We need to loosen the instance type hint of Unity objects when serializing
                // to counter a very specific issue that happens when:
                //  - We serialize a reference to an object of an editor type
                //  - That object type inherits a runtime type
                //  - The field supports the runtime type, but will allow the editor type
                //  - Therefore serializing as the editor type is valid, but will fail to deserialize in builds
                // The only current example of this bug is AudioMixers and AudioMixerGroups.
                // UnityEDITOR.Audio.AudioMixerController extends UnityENGINE.Audio.AudioMixer.
                // UnityEDITOR.Audio.AudioMixerGroupController extends UnityENGINE.Audio.AudioMixerGroup.
                // Therefore, if we serialize a type hint to the editor controller, e.g. AudioMixerGroupController,
                // builds will fail to deserialize the type hint, even though they don't actually need it
                // to properly fetch the Unity Object reference, because it's provided directly by the converter.
                // We must instead serialize a type hint to the runtime, non-controller type, e.g. AudioMixer.
                // However, when loosening our type, we must make sure not to go past the compatibility
                // with the defined storage type, because if we did, we would get the "Ignoring type specifier"
                // error defined below, as the instance type hint wouldn't be assignable to the storage type on deserialization.
                // Likewise, we must make sure not to go above UnityObject itself, because we need that much hinting
                // for FullSerializer to know that the proper converter to be used is our custom UnityObjectConverter.
                // See: https://support.ludiq.io/communities/5/topics/1032-audio-mixer-reference-gets-nulled-on-il2cpp-builds
                if (instance is UnityObject)
                {
                    var looseType = instanceType;

                    do
                    {
                        instanceType = looseType;
                        looseType    = looseType.BaseType;
                    }while (looseType != null && instanceType != typeof(UnityObject) && storageType.IsAssignableFrom(looseType));

                    // Debug.Log($"Loosened instance type hint for {instance.GetType()} stored as {storageType} to {instanceType}");
                }

                // Add the inheritance metadata
                EnsureDictionary(data);
                data.AsDictionary[Key_InstanceType] = new fsData(RuntimeCodebase.SerializeType(instanceType));
            }

            return(serializeResult);
        }