Custom type cannot be serialized even after registration.

Hi.

I registered 2 types and want to use them in Dictionary.
Class with my types:

public static class MyTypes {

public static void Register()
{
PhotonPeer.RegisterType(typeof(IntVector2), (byte)'O', SerializeIntVector2, DeserializeIntVector2);
PhotonPeer.RegisterType(typeof(Color32), (byte)'R', SerializeColor32, DeserializeColor32);
Debug.Log("Custom types have been registered");
}

private const byte IntVector2Size = 2 * 4;
private const byte Color32Size = 4 * 2;

public static readonly byte[] MemoryIntVector2 = new byte[IntVector2Size];
public static readonly byte[] MemoryColor32 = new byte[Color32Size];

private static short SerializeIntVector2(StreamBuffer outStream, object customobject)
{
IntVector2 vo = (IntVector2)customobject;
lock (MemoryIntVector2)
{
byte[] bytes = MemoryIntVector2;
int index = 0;
Protocol.Serialize(vo.x, bytes, ref index);
Protocol.Serialize(vo.y, bytes, ref index);
outStream.Write(bytes, 0, IntVector2Size);
}

return IntVector2Size;
}

private static object DeserializeIntVector2(StreamBuffer inStream, short length)
{
IntVector2 vo = new IntVector2();
lock (MemoryIntVector2)
{
inStream.Read(MemoryIntVector2, 0, IntVector2Size);
int index = 0;
Protocol.Deserialize(out vo.x, MemoryIntVector2, ref index);
Protocol.Deserialize(out vo.y, MemoryIntVector2, ref index);
}

return vo;
}

private static short SerializeColor32(StreamBuffer outStream, object customobject)
{
Color32 vo = (Color32)customobject;
lock (MemoryIntVector2)
{
byte[] bytes = MemoryColor32;
int index = 0;
Protocol.Serialize(vo.r, bytes, ref index);
Protocol.Serialize(vo.g, bytes, ref index);
Protocol.Serialize(vo.b, bytes, ref index);
Protocol.Serialize(vo.a, bytes, ref index);
outStream.Write(bytes, 0, Color32Size);
}

return Color32Size;
}

private static object DeserializeColor32(StreamBuffer inStream, short length)
{
Color32 vo = new Color32();
lock (MemoryColor32)
{
inStream.Read(MemoryIntVector2, 0, Color32Size);
int index = 0;
var r = (short) vo.r;
var g = (short)vo.g;
var b = (short)vo.b;
var a = (short)vo.a;
Protocol.Deserialize(out r, MemoryColor32, ref index);
Protocol.Deserialize(out g, MemoryColor32, ref index);
Protocol.Deserialize(out b, MemoryColor32, ref index);
Protocol.Deserialize(out a, MemoryColor32, ref index);
}

return vo;
}
}


i tried to serialize Dictionary<IntVector2, Color32> and got an error:

Exception: Unexpected - cannot serialize Dictionary with key type: Assets.Scripts.Common.IntVector2
ExitGames.Client.Photon.Protocol16.SerializeDictionaryHeader (ExitGames.Client.Photon.StreamBuffer writer, System.Object dict, System.Boolean& setKeyType, System.Boolean& setValueType)
ExitGames.Client.Photon.Protocol16.SerializeDictionary (ExitGames.Client.Photon.StreamBuffer dout, IDictionary serObject, Boolean setType)
ExitGames.Client.Photon.Protocol16.Serialize (ExitGames.Client.Photon.StreamBuffer dout, System.Object serObject, Boolean setType)
ExitGames.Client.Photon.Protocol16.SerializeHashTable (ExitGames.Client.Photon.StreamBuffer dout, ExitGames.Client.Photon.Hashtable serObject, Boolean setType)
ExitGames.Client.Photon.Protocol16.Serialize (ExitGames.Client.Photon.StreamBuffer dout, System.Object serObject, Boolean setType)
ExitGames.Client.Photon.Protocol16.SerializeParameterTable (ExitGames.Client.Photon.StreamBuffer stream, System.Collections.Generic.Dictionary`2 parameters)
ExitGames.Client.Photon.Protocol16.SerializeOperationRequest (ExitGames.Client.Photon.StreamBuffer stream, Byte operationCode, System.Collections.Generic.Dictionary`2 parameters, Boolean setType)
ExitGames.Client.Photon.EnetPeer.SerializeOperationToMessage (Byte opCode, System.Collections.Generic.Dictionary`2 parameters, EgMessageType messageType, Boolean encrypt)
ExitGames.Client.Photon.EnetPeer.EnqueueOperation (System.Collections.Generic.Dictionary`2 parameters, Byte opCode, Boolean sendReliable, Byte channelId, Boolean encrypt, EgMessageType messageType)
ExitGames.Client.Photon.PeerBase.EnqueueOperation (System.Collections.Generic.Dictionary`2 parameters, Byte opCode, Boolean sendReliable, Byte channelId, Boolean encrypted)
ExitGames.Client.Photon.PhotonPeer.OpCustom (Byte customOpCode, System.Collections.Generic.Dictionary`2 customOpParameters, Boolean sendReliable, Byte channelId, Boolean encrypt)
LoadBalancingPeer.OpSetPropertiesOfRoom (ExitGames.Client.Photon.Hashtable gameProperties, ExitGames.Client.Photon.Hashtable expectedProperties, Boolean webForward) (at Assets/Photon Unity Networking/Plugins/PhotonNetwork/LoadbalancingPeer.cs:519)
Room.SetCustomProperties (ExitGames.Client.Photon.Hashtable propertiesToSet, ExitGames.Client.Photon.Hashtable expectedValues, Boolean webForward) (at Assets/Photon Unity Networking/Plugins/PhotonNetwork/Room.cs:275)
RoomNetworkController.LeaveRoom () (at Assets/Scripts/Room/RoomNetworkController.cs:88)
RoomMenuPanel.OnLeaveRoomPressed () (at Assets/Scripts/Room/MenuPanels/RoomMenuPanel.cs:27)
UnityEngine.Events.InvokableCall.Invoke (System.Object[] args) (at C:/buildslave/unity/build/Runtime/Export/UnityEvent.cs:154)
UnityEngine.Events.InvokableCallList.Invoke (System.Object[] parameters) (at C:/buildslave/unity/build/Runtime/Export/UnityEvent.cs:637)
UnityEngine.Events.UnityEventBase.Invoke (System.Object[] parameters) (at C:/buildslave/unity/build/Runtime/Export/UnityEvent.cs:773)
UnityEngine.Events.UnityEvent.Invoke () (at C:/buildslave/unity/build/Runtime/Export/UnityEvent_0.cs:52)
UnityEngine.UI.Button.Press () (at C:/buildslave/unity/build/Extensions/guisystem/UnityEngine.UI/UI/Core/Button.cs:35)
UnityEngine.UI.Button.OnPointerClick (UnityEngine.EventSystems.PointerEventData eventData) (at C:/buildslave/unity/build/Extensions/guisystem/UnityEngine.UI/UI/Core/Button.cs:44)
UnityEngine.EventSystems.ExecuteEvents.Execute (IPointerClickHandler handler, UnityEngine.EventSystems.BaseEventData eventData) (at C:/buildslave/unity/build/Extensions/guisystem/UnityEngine.UI/EventSystem/ExecuteEvents.cs:50)
UnityEngine.EventSystems.ExecuteEvents.Execute[IPointerClickHandler] (UnityEngine.GameObject target, UnityEngine.EventSystems.BaseEventData eventData, UnityEngine.EventSystems.EventFunction`1 functor) (at C:/buildslave/unity/build/Extensions/guisystem/UnityEngine.UI/EventSystem/ExecuteEvents.cs:261)
UnityEngine.EventSystems.ExecuteEvents:ExecuteHierarchy(GameObject, BaseEventData, EventFunction`1)
VRTK.VRTK_VRInputModule:AttemptClick(VRTK_UIPointer) (at Assets/VRTK/Scripts/Internal/VRTK_VRInputModule.cs:253)
VRTK.VRTK_VRInputModule:ClickOnDown(VRTK_UIPointer, List`1, Boolean) (at Assets/VRTK/Scripts/Internal/VRTK_VRInputModule.cs:203)
VRTK.VRTK_VRInputModule:Click(VRTK_UIPointer, List`1) (at Assets/VRTK/Scripts/Internal/VRTK_VRInputModule.cs:181)
VRTK.VRTK_VRInputModule:Process() (at Assets/VRTK/Scripts/Internal/VRTK_VRInputModule.cs:38)
VRTK.VRTK_EventSystem:Update() (at Assets/VRTK/Scripts/Internal/VRTK_EventSystem.cs:50)


What I did wrong?

Comments

  • JohnTube
    JohnTube ✭✭✭✭✭
    Hi @dNazarik,

    According to the documentation, Dictionary with custom type is not supported.
    @Kaiserludi can confirm.
  • @JohnTube:
    It definitely is supported on the server and in the C++ / objC Clients. In don't know for sure about the C# Clients, however I would be surprised if it wasn't supported there. @Tobias should be able to give a definitive answer.
  • It's currently not supported in the DotNet clients to serialize a custom Type in a generic Dictionary.
    You should be able to use a Hashtable.
    Both could be overhead you want to avoid. Custom types have overhead and a Dictionary, too. At least for networking, it makes sense to avoid this as much as possible, so using arrays, etc. is preferred - at least, if you send this multiple times per sec.