public static void OnBeforeSerializeImplementation <T>(T uo, ref FullSerializationData fullData, ref OdinSerializationData odinData, bool deserializationFailed) where T : UnityObject, ILudiqRootObject { // To prevent data loss, we don't serialize something that failed to deserialize in the first place if (deserializationFailed) { Debug.LogWarning($"Skipping serialization of {uo.ToSafeString()} to prevent data loss because it failed to deserialize.\n", uo); return; } // Run the user handler try { uo.OnBeforeSerialize(); } catch (Exception ex) { Debug.LogError($"Failed to run OnBeforeSerialize on {uo.ToSafeString()}.\n{ex}", uo); return; } // Check if we are migrating legacy FS data into OS to notify the user var migrating = fullData.ContainsRealData && !odinData.ContainsRealData(); try { // Serialize the data using OS only from now on odinData = uo.OdinSerialize(ref odinData); if (migrating) { // Clear the legacy FS data so that it isn't used as a fallback during deserialization from now on. fullData = default; Debug.Log($"Migrated legacy serialization data on {uo.ToSafeString()} from Full Serializer to Odin Serializer.\n", uo); } } catch (Exception ex) { Debug.LogError($"Failed to serialize {uo.ToSafeString()} using Odin Serializer.\n{ex}", uo); return; } // Run the user handler try { uo.OnAfterSerialize(); } catch (Exception ex) { Debug.LogError($"Failed to run OnAfterSerialize on {uo.ToSafeString()}.\n{ex}", uo); return; } }
public static void OnAfterDeserializeImplementation <T>(T uo, FullSerializationData fullData, OdinSerializationData odinData, ref bool deserializationFailed) where T : UnityObject, ILudiqRootObject { // Set a flag to indicate to our API checker that Unity calls are forbidden isUnityDeserializing = true; try { object _this = uo; // If we don't reach the complete end of the process for any reason, the failure flag will be set. deserializationFailed = true; // Run the user callback try { uo.OnBeforeDeserialize(); } catch (Exception ex) { Debug.LogError($"Failed to run OnBeforeDeserialize on {uo.ToSafeString()}.\n{ex}", uo); return; } // Deserialize with OS data if it is available if (odinData.ContainsRealData()) { try { odinData.OdinDeserializeInto(ref _this); } catch (Exception ex) { Debug.LogError($"Failed to deserialize {uo.ToSafeString()} using Odin Serializer.\n{ex}", uo); return; } } // In theory, there shouldn't be a case where we have both OS and FS data because we clear the FS data on a successful OS deserialization. // Just to be absolutely safe we don't rollback to earlier FS data though, we're being mutually exclusive on deserialization too. else { // Fallback to legacy FS data try { fullData.FullDeserializeInto(ref _this, true); } catch (Exception ex) { Debug.LogError($"Failed to deserialize {uo.ToSafeString()} using legacy Full Serializer data.\n{ex}", uo); return; } } // Run the user callback try { uo.OnAfterDeserialize(); } catch (Exception ex) { Debug.LogError($"Failed to run OnAfterDeserialize on {uo.ToSafeString()}.\n{ex}", uo); return; } // We managed to execute everything successfully, clear the failure flag. deserializationFailed = false; } finally { // Clear our API lock regardless of what happened isUnityDeserializing = false; } }