C# serialization to PlayerPrefs -> exceptions only in Editor!

This is kinda bizarre! Here is my code to serialize a class marked as [Serializable] to PlayerPrefs__. It’s working perfectly on my player build (iOS). I can even rearrange/add properties to the class, then compile and the runtime is still able to deserialize and instantiate the object correctly. Sweet.__

The bizarre part is it doesn’t work in the Editor. I am getting this exception on Load(). Why would it work in the runtime but not in the editor? Any ideas oh C# gurus? Could the [Serializable] flag on my class be mixing up the Editor? Thanks!

using UnityEngine;
using System;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;

public class PlayerPrefsSerializer  
{
	private static BinaryFormatter bf = new BinaryFormatter ();
		
	public static void Save (string prefKey, object serializableObject)
	{
		if (serializableObject == null)
			return;
		Debug.Log (string.Format ("Saving: {0} => {1}", prefKey, serializableObject.GetType ()));
		MemoryStream memoryStream = new MemoryStream ();
		bf.Serialize (memoryStream, serializableObject);
		string serializedData = System.Convert.ToBase64String (memoryStream.ToArray ());
		PlayerPrefs.SetString (prefKey, serializedData);
		Debug.Log (string.Format ("Saved serialized data {0}", serializedData));
	}
	
	public static object Load (string prefKey)
	{
		if (!PlayerPrefs.HasKey (prefKey))
			return null;
		
		string serializedData = PlayerPrefs.GetString (prefKey, String.Empty);
		if (serializedData == String.Empty)
			return null;
		
		Debug.Log (string.Format ("Loading serialized data {0} {1}", prefKey, serializedData));		
		MemoryStream dataStream = new MemoryStream (System.Convert.FromBase64String (serializedData));
		object result = bf.Deserialize (dataStream);		
		Debug.Log (string.Format ("Loaded: {0} => {1}", prefKey, result.GetType ()));				
		return result;
	}
}

I’m guessing because it’s using the BinaryFormatter. I haven’t used that much (I’m an XmlSerializer kinda guy), but from what I understand it’s pretty tied to assemblies and their versions, and from the looks of it the Editor uses temporary/on-the-fly-compiled assemblies, so maybe that’s the issue. Can you switch it up to XmlSerialization instead of using a BinaryFormatter?

Yes, I suspected the same- it’s really the only explanation I could think of. I was trying to avoid depending on XML (and adding more .dlls to my player build). But I should definitely try that for the sake of understanding what’s going on.

Or maybe I could use XML serialization in the Editor, and BinaryFormatter in the player build!!

I was just thinking the same thing; you could likely use the compiler flags (http://unity3d.com/support/documentation/Manual/Platform%20Dependent%20Compilation.html) to target either platform. Just double-check your output size so that it doesn’t include the extra DLLs for non-applicable builds.

Excellent- the XML serialization is working in the editor, and the compiler flags to produce my optimal code for player build. Thanks

If you included the XML serialization in your other builds, does it inflate the size much? I only ask because if you plan to issue new versions of your game but still be backward-compatible with legacy save data, you might possibly run into issues for similar reasons.

Yes, just using XMLSerializer adds about 6MB of .dlls to the build! (System.Xml plus various other dependencies)
Also this note from the manual:

So I am going to go with the BinaryFormatter method on iOS- it apparently only adds a .dll about 8KB: System.Core.dll
Also going to tag the PlayerPref key with the version number of my app, so that I won’t accidentally try to deserialize incompatible data. I will of course have to write a migration method if the classes change from version to version but that’s OK.

Ahh, good good. Interesting that it’s adding 6mb for you. I’m using the XmlSerializer and my total web player unity size (including all assets/code) is only 933kb.