Some confusion as to Photon Serialization

Options
I'm a bit confused as Photon seems to not be permitting a serialization that this page implies should be legitimate by default. The table specifies that array (array of type T, T[]) is legal. I can confirm this by using an array of a primitive as an argument for an RPC call with no issue. The table also specifies that
T-type can be any of the types listed in this table except byte.
Cool. The table specifies that Dictionary<K,V> is legal, and once again I can confirm this by sending a Dictionary of two primitive types over an RPC call without issue. However, when attempting to combine this information in order to send Dictionary<K,V>[], the following error will always occur


IndexOutOfRangeException: Array index is out of range. ExitGames.Client.Photon.Protocol16.SerializeDictionaryHeader (ExitGames.Client.Photon.StreamBuffer writer, System.Object dict, System.Boolean& setKeyType, System.Boolean& setValueType) ExitGames.Client.Photon.Protocol16.SerializeArray (ExitGames.Client.Photon.StreamBuffer dout, System.Array serObject, Boolean setType) ExitGames.Client.Photon.Protocol16.Serialize (ExitGames.Client.Photon.StreamBuffer dout, System.Object serObject, Boolean setType) ExitGames.Client.Photon.Protocol16.SerializeObjectArray (ExitGames.Client.Photon.StreamBuffer dout, System.Object[] objects, 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.TPeer.SerializeOperationToMessage (Byte opc, System.Collections.Generic.Dictionary`2 parameters, EgMessageType messageType, Boolean encrypt) ExitGames.Client.Photon.TPeer.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.OpRaiseEvent (Byte eventCode, System.Object customEventContent, Boolean sendReliable, .RaiseEventOptions raiseEventOptions) (at Assets/Photon Unity Networking/Plugins/PhotonNetwork/LoadbalancingPeer.cs:779) NetworkingPeer.OpRaiseEvent (Byte eventCode, System.Object customEventContent, Boolean sendReliable, .RaiseEventOptions raiseEventOptions) (at Assets/Photon Unity Networking/Plugins/PhotonNetwork/NetworkingPeer.cs:1012) NetworkingPeer.RPC (.PhotonView view, System.String methodName, PhotonTargets target, .PhotonPlayer player, Boolean encrypt, System.Object[] parameters) (at Assets/Photon Unity Networking/Plugins/PhotonNetwork/NetworkingPeer.cs:3804) PhotonNetwork.RPC (.PhotonView view, System.String methodName, .PhotonPlayer targetPlayer, Boolean encrpyt, System.Object[] parameters) (at Assets/Photon Unity Networking/Plugins/PhotonNetwork/PhotonNetwork.cs:2998) PhotonView.RPC (System.String methodName, .PhotonPlayer targetPlayer, System.Object[] parameters) (at Assets/Photon Unity Networking/Plugins/PhotonNetwork/PhotonView.cs:646) MatchProxy.registerTeam (System.Collections.Generic.Dictionary`2[] team) (at Assets/Scripts/Battle/MatchProxy.cs:29) Match.startMatch () (at Assets/Scripts/Battle/Match.cs:74) ServerProxy.startMatch () (at Assets/Scripts/Battle/Client/ServerProxy.cs:29) System.Reflection.MonoMethod.Invoke (System.Object obj, BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) (at /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.Reflection/MonoMethod.cs:222) Rethrow as TargetInvocationException: Exception has been thrown by the target of an invocation. System.Reflection.MonoMethod.Invoke (System.Object obj, BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) (at /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.Reflection/MonoMethod.cs:232) System.Reflection.MethodBase.Invoke (System.Object obj, System.Object[] parameters) (at /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.Reflection/MethodBase.cs:115) NetworkingPeer.ExecuteRpc (ExitGames.Client.Photon.Hashtable rpcData, Int32 senderID) (at Assets/Photon Unity Networking/Plugins/PhotonNetwork/NetworkingPeer.cs:2985) NetworkingPeer.OnEvent (ExitGames.Client.Photon.EventData photonEvent) (at Assets/Photon Unity Networking/Plugins/PhotonNetwork/NetworkingPeer.cs:2578) ExitGames.Client.Photon.PeerBase.DeserializeMessageAndCallback (System.Byte[] inBuff) ExitGames.Client.Photon.TPeer.DispatchIncomingCommands () ExitGames.Client.Photon.PhotonPeer.DispatchIncomingCommands () PhotonHandler.Update () (at Assets/Photon Unity Networking/Plugins/PhotonNetwork/PhotonHandler.cs:157)


Original RPC Call:
Match.m.photonView.RPC("registerTeam", PhotonNetwork.masterClient, (object)team);


Original RPC Reception:
[PunRPC] public void registerTeam(Dictionary<string, string>[] team, PhotonMessageInfo info) { Match.m.registerTeam(info.sender.ID, team); }

According to the table, this should work, as arrays should work with any other type in the table (according to the description), and Dictionaries are in the table. So what's up? Am I misusing/misunderstanding the RPC, is the serialization page inaccurate, or is there a bug I should be aware of?

Comments

  • [Deleted User]
    Options
    Hi @Ignoritus,

    you are right, that this is not working although the documentation states something else. I can confirm that I get the same error. Maybe @Tobias can give an answer, if this is a bug or if the documentation is wrong in this case.

    However is this really a use case for your project or did you just tried something out? I'm asking because an array of dictionaries doesn't seem to be a good solution at all. From the code snippets I see that you are doing something with 'teams'. There is a PunTeams script included in the PUN package you can take a look at. Maybe this one also provides the functionality you are looking for.
  • Ignoritus
    Ignoritus
    edited May 2018
    Options

    Hi @Ignoritus,

    you are right, that this is not working although the documentation states something else. I can confirm that I get the same error. Maybe @Tobias can give an answer, if this is a bug or if the documentation is wrong in this case.

    However is this really a use case for your project or did you just tried something out? I'm asking because an array of dictionaries doesn't seem to be a good solution at all. From the code snippets I see that you are doing something with 'teams'. There is a PunTeams script included in the PUN package you can take a look at. Maybe this one also provides the functionality you are looking for.

    Thanks for the response.

    "Teams" here does not refer to teams of players, but the team of characters you have selected. Since characters have many customizable aspects, there is a decent amount of information that should be sent to the server and then redistributed to the clients about your personalized choices. If you have any alternative suggestions, I am all ears. I selected an array of dictionaries because the only alternative I see for sending this information would be creating a custom object that will ultimately likely be little more than a dictionary under the hood anyways.
  • [Deleted User]
    Options
    If you have player specific data, you might consider using the Custom Player Properties for storing and synchronizing these data. This properties are represented by a Hashtable (basically a Dictionary) where you can store Key-Value-Pairs. When modifying those properties, the changes get synchronized automatically. You can set properties by using PhotonNetwork.player.SetCustomProperties(Hashtable propertiesToSet);. When a client receives the updated properties, the OnPhotonPlayerPropertiesChanged callback will be called.

    Example:
    void OnPhotonPlayerPropertiesChanged(object[] playerAndUpdatedProps) 
    {
        PhotonPlayer player = playerAndUpdatedProps[0] as PhotonPlayer;
        Hashtable props = playerAndUpdatedProps[1] as Hashtable;
        //...
    }