How to serialize a custom class to send to clients via RPC?

Each player has a PlayerControl class, and I want every client in a room to have each player's instance of their PlayerControl class. This will allow the game's GameRules class to send RPC's and affect the values of each player's PlayerControl class. I want to send the PlayerControl via RPC when starting the game, but I don't know how.

I have looked at forum posts from many years ago and also studied the CustomTypes.cs script. At first I followed the answer in https://forum.unity3d.com/threads/pun-serialization.405031/ , marked my PlayerControl class as serializable, and used my newly created Serialize and Deserialize functions, but came up with an error.

I'd like to try out the CustomTypes.cs method of serializing a custom class and registering the type as it seems more straight forward. Anyone have any tips on how to convert the examples in CustomTypes.cs to allow serializing a custom class? In the custom type examples, they are mostly dealing with float values when serializing Vectors and quaternions. How would it be different if I wanted a custom class to be serialized? I appreciate the help in advance.

Answers

  • Any help on this would really be appreciated.
  • Hi,

    serializing your class isn't different than picking the x, y properties or a vector2 really, you simply go over all your class properties and serialize/deserialize them in a byte-array. Don't overthink this.

    Let me know if you keep struggling with this, I'll come up with a sample.

    Bye,

    Jean
  • Tobias
    Tobias admin
    edited October 2016
    CustomTypes have some overhead, as we need to send how long your (serialized) data is. So for types with only little info, don't use this, unless it makes your life way easier.
    https://doc.photonengine.com/en-us/pun/current/reference/serialization-in-photon
  • Hi,

    So do you still want to go for custom class serialization? Don't forget that internaly, we have a CustomTypes.cs class doing just that, so simply inspire from that, it features everything you need to get started doing your own serialization of your own classes. It's in Photon Unity Networking/Plugins(PhotonNetwork/

    Bye,

    Jean
  • There is no complete example which shows how to serialize a custom class and how to send/receive data using RPC. I have a following custom class and I want to serialize this class for sending data to other clients.

    Public class TransferredData
    {
    public Vector3[] m_vertices;
    public int[] m_indices;
    public TransferredDate(Vector3[] vertices, int[] indices)
    {.....}
    }

    I tried but nothing is sent to other clients.
  • jeanfabre
    jeanfabre mod
    edited June 2017
    Hi,

    Firs thing, given your class, it seems you want to share large amounts of data, consider sharing the parameters that leads to the mesh definition, instead of the definition itself ( like Mecanim affects animation using simple parameters).

    this point aside, here's a script showing how to do this with your class.

    basically, you create a serializer and deserializer and then register your type to Photon using PhotonPeer.RegisterType() so that it knows what method to invoke when it finds one.

    the example below it not bullet proof, but is a good start to understand what is at stake for custom class serializations for Photon.

    using ExitGames.Client.DemoParticle; using ExitGames.Client.Photon; using UnityEngine; using System.Linq; [RequireComponent(typeof(PhotonView))] public class CustomClassRpcs : Photon.MonoBehaviour { public int RpcIntervalSeconds = 2; private TimeKeeper InstantiateTimer; void Start() { PhotonPeer.RegisterType(typeof (CustomClassTest), (byte) 'A', SerializeCustomClassTest, DeserializeCustomClassTest); InstantiateTimer = new TimeKeeper(RpcIntervalSeconds*1000); } private int rpcCallCounter = 0; private int lastRpcCallId = 0; private int rpcCalledCounter = 0; public void Update() { if (OnIntervalInstantiate.pause) { return; } if (this.photonView.isMine) { if (InstantiateTimer.ShouldExecute) { InstantiateTimer.Reset(); CustomClassTest _t = new CustomClassTest(); _t.m_indices = new int[]{1,2,3}; _t.m_vertices = new Vector3[]{Vector3.zero,Vector3.one}; this.photonView.RPC("SomeRpc", PhotonTargets.All,_t); } } } [PunRPC] public void SomeRpc(CustomClassTest t) { string result = "Result: "; if (t.m_indices!=null) { result += "Indices : "; foreach(int _i in t.m_indices) { result += " "+_i; } } if (t.m_vertices!=null) { result += " Vertices : "; foreach(Vector3 _v in t.m_vertices) { result += " "+_v; } } Debug.Log(result); } static byte[] SerializeCustomClassTest(object customObject) { CustomClassTest so = (CustomClassTest) customObject; //count of indices, following by indices, count of vertices followed by vertices object[] temp = new object[so.m_indices.Length+so.m_vertices.Length+2]; int i = 0; temp[i++] = so.m_indices.Length; foreach(int _i in so.m_indices) { temp[i++] = _i; } temp[i++] = so.m_vertices.Length; foreach(Vector3 _v in so.m_vertices) { temp[i++] = _v; } return Protocol.Serialize(temp); } static object DeserializeCustomClassTest(byte[] bytes) { CustomClassTest so = new CustomClassTest(); object[] tmp = (object[]) Protocol.Deserialize(bytes); int o_i = 0; int _indicesCount = (int)tmp[o_i++]; if (tmp.Length>o_i+_indicesCount-1) { so.m_indices = new int[_indicesCount]; for(int i=0;i<_indicesCount;i++) { so.m_indices[i] = (int)tmp[o_i++]; } } int _verticesCount = (int)tmp[o_i++]; if (tmp.Length>o_i+_verticesCount-1) { so.m_vertices = new Vector3[_verticesCount]; for(int i=0;i<_verticesCount;i++) { so.m_vertices[i] = (Vector3)tmp[o_i++]; } } return (object) so; } } public class CustomClassTest { public int[] m_indices; public Vector3[] m_vertices; }
    Let me know if you have questions :)

    Bye,

    Jean
  • Thanks Jean. It works well. But there is a problem when I use 2 scenes with RPC, one for sending data and the other for receiving and processing data. The error message looks like "Received RPC "SomeRpc" for viewID 1 but this PhotonView does not exist! Was remote PV. Remote called. By: 1 Maybe GO was destroyed but RPC not cleaned up".

    Have you experienced such problem?
  • Hi,

    that's already a different problem indeed. Can you make open a new thread on this and ping me on that new thread? then it will be easier to follow.

    Bye,

    Jean
  • @jeanfabre: Thanks for the reply. There is a problem as sending a large amount of data. Is there any limitation about amount of data we send from one player to another player?