- Home /
Help with Binary serialization/de-serialization of List items and the WEBPLAYER
The simplified code below will successfully serialize and de-serialize (binary format) Lists and objects in the editor and stand alone games.
When run this code on a web player I receive the following error during de-serialization only:
System.FieldAccessException: Attempt to access a private/protected field failed.
If I rework the code to serialize and de-serialize simple objects it will work on the web player.
From my reading of the mono compatibility table it seems that this should be supported on the web player.
What am I missing? does the webplayer support binary serialization/de-serialization of List items? Must I switch to another format for serialization/de-serialization?
using UnityEngine;
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;
using System.Text;
using System.Reflection;
using System.Collections;
public class SerialTestList : MonoBehaviour
{
// testing using lists
public List<Player> Players = new List<Player>();
public List<Player> PlayersDecoded = new List<Player>();
public void Start()
{
// Creat some data in our simple list
Players.Add(new Player(1, "Tom", "Jones", "SeattleFella", "A cool guy", "", 1));
Players.Add(new Player(2, "Bob", "Smith", "NYFella", "A Hot guy", "", 2));
Players.Add(new Player(3, "Jim", "Jones", "BostonFella", "A white guy", "", 3));
// create a stream to hold the serialized data
System.IO.MemoryStream _MemoryStream = new System.IO.MemoryStream();
// Encode the data into a binary stream
try {
// create the binary formatter
IFormatter formatterEncode = new BinaryFormatter();
formatterEncode.Binder = new VersionDeserializationBinder();
// serialize the collection
formatterEncode.Serialize(_MemoryStream, Players);
}
catch (Exception e) {
Debug.LogError(e + "Exception caught in encoding");
}
try
{
// create the binary formatter
IFormatter formatterDecode = new BinaryFormatter();
formatterDecode.Binder = new VersionDeserializationBinder();
// set memory stream position to starting point
_MemoryStream.Position = 0;
// deserialize the collection from the stream
PlayersDecoded = (List<Player>)formatterDecode.Deserialize(_MemoryStream); // ERROR HERE
}
catch (Exception e)
{
Debug.LogError(e + "Exception caught in Decoding");
}
// Display the shrunk and reExpanded list in the debugger
foreach (Player _plr in PlayersDecoded)
{
Debug.Log(_plr.FirstName + " " + _plr.LastName);
}
}
}
[System.Serializable]
public class Player
{
//public string FirstName { get; set; }
//public string LastName { get; set; }
//public string Handle { get; set; }
//public string About { get; set; }
//public string AvatarURL { get; set; }
//public int PlayerID { get; set; }
//public int Id { get; set; }
public string FirstName ;
public string LastName ;
public string Handle ;
public string About;
public string AvatarURL ;
public int PlayerID ;
public int Id;
public Player(int _id = 0, string _fn = null, string _ln = null, String _hdl = null, string _abt = null, string _avaUrl = null, int _pid = 0)
{
this.Id = _id;
this.FirstName = _fn;
this.LastName = _ln;
this.Handle = _hdl;
this.About = _abt;
this.AvatarURL = _avaUrl;
this.PlayerID = _pid;
}
}
// === This is required to guarantee a fixed serialization assembly name, which Unity likes to randomize on each compile
// Do not change this
public sealed class VersionDeserializationBinder : SerializationBinder
{
public override Type BindToType(string assemblyName, string typeName) {
if (!string.IsNullOrEmpty(assemblyName) && !string.IsNullOrEmpty(typeName)) {
Type typeToDeserialize = null;
assemblyName = Assembly.GetExecutingAssembly().FullName;
// The following line of code returns the type.
typeToDeserialize = Type.GetType(String.Format("{0}, {1}", typeName, assemblyName));
return typeToDeserialize;
}
return null;
}
}
I am facing the same problem. Did you find a solution/work around this ? Please share. Thanks in advance.
Answer by Seattlefella · May 25, 2013 at 04:14 PM
Yes I did get all to work.
The error comes from unity producing a differently named assembly on each build which causes problems with serialisation of contained classes.
A workaround is to define all data classes for serialisation in external assemblies.
A more complete answer can be found on this thread http://forum.unity3d.com/threads/16281-Unity-BinaryFormatter-Deserialization-Problem
thanks for your reply. I too solved my problem, not through different assemblies but by using ISerializable interface and providing GetObjectData() and serializing constructor() and handling List and Dictionary myself.