- Home /
Serialization\Deserialization problem
I have posted a similar question to this one, but I had to do some changes to the code so I ended up creating a new question. (http://answers.unity3d.com/questions/869284/serialize-an-array-of-custom-objects.html)
I have a Team class that (now) has an LauncherPlayer[] array that stores info about the players. Serialization\deserialziation methods for this class I know they are working fine because I already tested them.
The problem is that in my Team class I'am serializing that array, with no problems (I guess, at least I get no errors), but upon deserialization I get an object of type string instead of LauncherPlayer[] type.
public class Team
{
private int teamID;
private LauncherPlayer[] players;
private int playersJoined = 0;
}
public static byte[] serializeTeam(object o)
{
Team team = (Team)o;
var playerBytes = ExitGames.Client.Photon.Protocol.Serialize(team.players);
//Lenght = playerBytes.Lenght + (4 * 3) (4 bytes in size, 3 ints)
byte[] bytes = new byte[playerBytes.Length + 12];
int index = 0;
ExitGames.Client.Photon.Protocol.Serialize(team.teamID, bytes, ref index);
//We need to store the lenght for deserialization
ExitGames.Client.Photon.Protocol.Serialize(playerBytes.Length, bytes, ref index);
System.Array.Copy(playerBytes, 0, bytes, index, playerBytes.Length);
index += playerBytes.Length;
ExitGames.Client.Photon.Protocol.Serialize(team.playersJoined, bytes, ref index);
return bytes;
}
public static object deserializeTeam(byte[] bytes)
{
Team team = new Team();
int index = 0;
int playerBytesLength;
ExitGames.Client.Photon.Protocol.Deserialize(out team.teamID, bytes, ref index);
ExitGames.Client.Photon.Protocol.Deserialize(out playerBytesLength, bytes, ref index);
var playerBytes = new byte[playerBytesLength];
System.Array.Copy(bytes, index, playerBytes, 0, playerBytesLength);
index += playerBytes.Length;
Debug.Log(ExitGames.Client.Photon.Protocol.Deserialize(playerBytes).GetType());
Debug.Log((string)ExitGames.Client.Photon.Protocol.Deserialize(playerBytes)+",");
//team.players = (LauncherPlayer[]) ExitGames.Client.Photon.Protocol.Deserialize(playerBytes);
ExitGames.Client.Photon.Protocol.Deserialize(out team.playersJoined, bytes, ref index);
return team;
}
public class LauncherPlayer {
private string playerName;
private int teamID = -1;
private int pos = -1;
private bool ready = false;
}
public static byte[] serializePlayer(object o)
{
LauncherPlayer player = (LauncherPlayer)o;
var nameBytes = ExitGames.Client.Photon.Protocol.Serialize(player.playerName);
//Lenght playerBytes.Lenght + (4 * 3) (4 bytes in size, 3 ints) + (1 byte from bool)
byte[] bytes = new byte[nameBytes.Length + 13];
int index = 0;
//We need to store the lenght for deserialization
ExitGames.Client.Photon.Protocol.Serialize(nameBytes.Length, bytes, ref index);
System.Array.Copy(nameBytes, 0, bytes, index, nameBytes.Length);
index += nameBytes.Length;
ExitGames.Client.Photon.Protocol.Serialize(player.teamID, bytes, ref index);
ExitGames.Client.Photon.Protocol.Serialize(player.pos, bytes, ref index);
bytes[index] = player.ready ? (byte) 1 : (byte) 0;
return bytes;
}
public static object deserializePlayer(byte[] bytes)
{
LauncherPlayer player = new LauncherPlayer();
int index = 0;
int nameBytesLenght;
ExitGames.Client.Photon.Protocol.Deserialize(out nameBytesLenght, bytes, ref index);
var nameBytes = new byte[nameBytesLenght];
System.Array.Copy(bytes, index, nameBytes, 0, nameBytesLenght);
player.playerName = (string)ExitGames.Client.Photon.Protocol.Deserialize(nameBytes);
index += nameBytes.Length;
ExitGames.Client.Photon.Protocol.Deserialize(out player.teamID, bytes, ref index);
ExitGames.Client.Photon.Protocol.Deserialize(out player.pos, bytes, ref index);
byte b = bytes [index];
player.ready = b == (byte)1 ? true : false;
return player;
}
Console output:
System.String
,
@ArkaneX I'am really sorry to bother you but since you helped me a lot on the last one, my guess is that I'am just failing something obvious
I anyone is interested to follow the discussion at Exit Games forum here is the link: http://forum.exitgames.com/viewtopic.php?f=17&t=5647
Answer by ArkaneX · Jan 15, 2015 at 06:52 PM
The only difference I see, is changed type of players
field, so this looks like a source of problem.
Photon knows how to serialize string
(and string[]
) types, but it doesn't know how to serialize LauncherPlayer
type. You need to register it, and provide serialize/deserialize methods for this type, the same way you did for Team
class.
EDIT
I checked the code of Serialize(object) method, and in my opinion it contains error. To serialize it uses a readonly MemoryStream, which is reused for each call. If at some point this stream has for example length of 10, then serializing an object which should result in 3-elements array, will still return 10-element array.
Anyway - I created a method, which can be used instead of Serialize(object), and in my tests it works:
public static byte[] SerializeObject(object obj)
{
var serializeMethod = typeof(ExitGames.Client.Photon.Protocol).GetMethod("Serialize",
System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic, null,
new System.Type[] { typeof(System.IO.MemoryStream), typeof(object), typeof(bool) }, null);
using (var ms = new System.IO.MemoryStream())
{
serializeMethod.Invoke(null, new object[] { ms, obj, true });
return ms.ToArray();
}
}
Please note that this uses reflection, so it is not blazing fast, and additionally might stop working in the next version of PUN.
I suggest posting this issue in ExitGame's forums, and asking for some guidance. Maybe their Serialize method was meant to be used in a different way?
Answer updated. I hope I wrote it clearly enough, because it's quite late here, and I'm slowly falling asleep...
Answer by Voxel-Busters · Aug 07, 2015 at 12:06 PM
For serializing you can choose c# Binary formatter or else third party plugin from asset store. I would also recommend you to check out our plugin Runtime Serialization for Unity which can serialize custom c# objects as well as Unity objects like GameObjects, Transform, MonoBehaviours etc. For complete list of supported types, please check this link.