Dictionary synchronization not working, and array sync sends even when there are no changes.

Options
I'm trying to synchronize Dictionary occupants

I tried doing
            if (stream.IsWriting)
            {
                stream.SendNext(occupants);
            }
            else
            {
                Debug.LogWarning("RECEIVING OCCUPANTS");
                occupants = (Dictionary<string, int>)stream.ReceiveNext();
            }
However this simply didn't work (I wouldn't see the RECEIVING OCCUPANTS message on the clients even when the master changed occupants.

So I changed it to the following

           if (stream.IsWriting)
            {
                Debug.LogWarning("SERIALIZING OCCUPANTS");
                List<string> keys = new List<string>(occupants.Keys);
                string[] keyArray = keys.ToArray();
                List<int> values = new List<int>(occupants.Values);
                int[] valueArray = values.ToArray();
                stream.SendNext(keyArray);
                stream.SendNext(valueArray);
            }
            else
            {
                Debug.LogWarning("RECEIVING OCCUPANTS");alue);
                string[] keyArray = (string[])stream.ReceiveNext();
                int[] valueArray = (int[])stream.ReceiveNext();
                occupants.Clear();
                for (int i = 0; i < keyArray.Length; ++i)
                {
                    occupants.Add(keyArray[i], valueArray[i]);
                }
            }
This works, but it's sending/receiving occupants every second, even when it doesn't change.

What is the proper procedure for synchronizing a dictionary? Are there any working examples? I haven't been able to find any.

Comments

  • CRho
    Options
    Also just to confirm I have tried it with both Unreliable on Change and Reliable Delta Compressed.
  • CRho
    Options
    Any insight? Is sync for dictionary and arrays simply not working?
  • CRho
    Options
    Can any Photon employees give insight? It's been a week since the original post. If Dictionary and List synchronization is not working properly then it should probably be removed from the documentation.
  • CRho
    Options
    Over 9 days since I posted, still no response...
  • jeanfabre
    Options
    Hi,

    on the technical issue itself: Let me try and repro this first, and I'll get back to you on my findings

    on the implementation: maybe this is not a good idea to synchronize this kind of values using a photonview. Can you explain the context? It seems that Player Custom properties would be a better place. How often is occupants data changing?

    Bye,

    Jean
  • jeanfabre
    Options
    Hi,

    also, I assume you are using pun 2, right?

    Bye,

    Jean
  • CRho
    Options
    Hi Jean,

    Thanks for the responses.

    The use case is that I'm synchronizing the occupancy of the game grid in a tactics game, i.e. mapping from grid coordinate to the ID of the actor that is in that grid location (no entry for grid coordinates that are empty). So it's essentially synchronizing the pairs of coordinates and actor IDs. The occupancy grid only changes when a character moves (it's pseudo-turn based, so this happens maybe once per second at max).

    Yes, I'm using PUN 2.
  • CRho
    Options
    Specifically, my server settings says PUN 2.14, photon lib 4.1.2.17
  • jeanfabre
    Options
    Hi,

    You need to set the observed option to "Unreliable", else it won't detect changes.

    I would strongly advice not do that and instead send each property individually like you did, or use custom properties, which would a lot better overal because you only change what really changed and you still get a callback via OnPlayerPropertiesUpdate

    https://doc-api.photonengine.com/en/pun/v2/interface_photon_1_1_realtime_1_1_i_in_room_callbacks.html#aabe61c5573a351d1abccb7059d252316

    Bye,

    Jean

  • CRho
    Options
    > You need to set the observed option to "Unreliable", else it won't detect changes.

    That seems a bit counter-intuitive. The docs seem to indicate that Reliable Delta compressed will detect and send only changes.

    > I would strongly advice not do that and instead send each property individually like you did

    The problem with sending arrays, as I stated in the original post, is that the array code above results in the array being synced constantly, even when it doesn't change. It is expected behavior that syncing only on change doesn't work properly for arrays?

    > or use custom properties

    Is there more in-depth documentation for custom properties anywhere? For example, can they be changed by any player or just the master client? When are they synced? If a player leaves and comes back, are they guaranteed to have the same room properties as all the other players? Etc.

    Room properties seemed to me like it was only used for actual properties of the room, like what stage level the room is on, team information, etc. It seems strange to me to use that for information about the game state instead of synchronization.
  • CRho
    Options
    Hi,

    I am still seeing that arrays are being sent and received in OnPhotonSerializeView even when they don't change.

    For example if you send an array of ints that's always { 0, 1, 2 }, then it will send constantly. This seems like a bug, or at the very least inefficiency in the synchronization code.
  • CRho
    Options
    I'm still having this issue.
  • jeanfabre
    Options
    Hi,

    As I said, your best option here is to use custom room or custom player properties, which will be optimal for your case. Using a PhotonView data serialization for this is not ideal, photonView Serialized Data is for data like position, which always changes, in your case, you want to synchronize discrete changes.

    instead of saving your occupants in an array, each player could have a custom property which is its occupant value. or use a single room custom property which your dictionnary.

    As for OnPhotonSerialiseView, we are not aware of any issues, so maybe you could us a minimal repro case?

    Bye,

    Jean
  • CRho
    Options
    Hi Jean,

    The minimal repro case is any array, I believe. If you just try to sync { 0, 1, 2 } in OnPhotonSerializeView, for example, and put a debug log in the receive portion, you'll see that the client is receiving the same data constantly even though it isn't changing.

    How reliable is using custom room/player properties? For example, if a client misses a message that a property has been updated, then will the client now be out of sync with the master and other clients? If a client reconnects and rejoins, do you have to put explicit logic to make that client fetch the properties (vs. with OnPhotonSerializeView where on reconnect it will automatically just receive the latest values)?
  • CRho
    Options
    Another qualm I have is that the documentation says custom properties should be used for "very infrequent changes" like doors being open vs. closed. The changes I'm trying to sync are discrete, but they happen fairly frequently (once every few seconds)
  • jeanfabre
    Options
    Hi,

    Once every few seconds is a very low rate, so yes custom properties is best suited for that.

    Bye,

    Jean