Ensure initial state of network-instantiated object, if that state changes over time?

Hi! I have a PhotonNetwork.Instantiated Sphere in the scene which the owning Player can color-change on click. Color changes happen with an RPC that passes the new integer for the colorIndex, but how can I ensure that when another player joins the room, they get the right current colorIndex? If I were to do the RPC using RpcTarget.AllBuffered instead of RpcTarget.All, then I understand the call would be called multiple times, but I only want the current colorIndex value.

In a sense, an answer to this -- only buffer last RPC -- would also solve my problem. As would having the ability to set a customProperties table for a specific photonView (instead of the Player, or the Room).

I'm aware of the ability to pass an initial data set during PhotonNetwork.Instantiate, but my issue is that the data changes over time. For what it's worth, in my other parts of the program where I have similar needs, I send one RPC to the Owner of that object, and then the owner replies with current state data in a reply RPC (but this would be a bit of a workaround for this). I suppose another approach would be to create a room customProperty with a kind of path syntax like owner-actorNumber + itemName, but that too seems like a workaround.

Thanks!

Comments

  • JohnTube
    JohnTube ✭✭✭✭✭
    Hi @Philipp,

    The actor who joins late will receive the instantiation event and will locally instantiate the prefab with the initial default color then the actor will receive all subsequent buffered RPC calls that change that color in order and apply them one by one and the last color should remain as expected. This should happen quickly that the player won't notice.

    Another approach would be to always clear previous buffered RPC calls of the same method that changes the color before calling a new buffered one. I don't think this is handled bu PUN out-of-the-box but should be doable.
  • Ok thanks! Do you know how I might do that, clearing the previous buffered RPC calls of the same method before calling the new buffered one?

    I'm asking not just for my little Mood Sphere object, but rather, that Sphere is part of a Gadget framework where people can later add many different interactive gadgets in front of them, so I'm trying to get it right, lean & optimized. Thanks!
  • JohnTube
    JohnTube ✭✭✭✭✭
    Hi @Philipp,

    Try using any of these methods after adding them to "PhotonNetworkPart.cs":
            public static bool OpCleanRpcBuffer(PhotonView view, string methodName)
            {
                rpcFilterByViewId.Clear();
                rpcFilterByViewId[keyByteZero] = view.ViewID;
                if (view.Prefix > 0)
                {
                    rpcFilterByViewId[keyByteOne] = (short)view.Prefix;
                }
                int shortcut = 0;
                if (rpcShortcuts.TryGetValue(methodName, out shortcut))
                {
                    rpcFilterByViewId[keyByteFive] = (byte)shortcut; // LIMITS RPC COUNT
                }
                else
                {
                    rpcFilterByViewId[keyByteThree] = methodName;
                }
                return PhotonNetwork.RaiseEventInternal(PunEvent.RPC, rpcFilterByViewId, OpCleanRpcBufferOptions, SendOptions.SendReliable);
            }
    
            public static bool OpCleanRpcBuffer(PhotonView view, string methodName, params object[] parameters)
            {
                rpcFilterByViewId.Clear();
                rpcFilterByViewId[keyByteZero] = view.ViewID;
                if (view.Prefix > 0)
                {
                    rpcFilterByViewId[keyByteOne] = (short)view.Prefix;
                }
                int shortcut = 0;
                if (rpcShortcuts.TryGetValue(methodName, out shortcut))
                {
                    rpcFilterByViewId[keyByteFive] = (byte)shortcut; // LIMITS RPC COUNT
                }
                else
                {
                    rpcFilterByViewId[keyByteThree] = methodName;
                }
                if (parameters != null && parameters.Length > 0)
                {
                    rpcFilterByViewId[keyByteFour] = parameters;
                }
                return PhotonNetwork.RaiseEventInternal(PunEvent.RPC, rpcFilterByViewId, OpCleanRpcBufferOptions, SendOptions.SendReliable);
            }
    
            public static bool OpCleanRpcBuffer(string methodName, params object[] parameters)
            {
                rpcFilterByViewId.Clear();
                int shortcut = 0;
                if (rpcShortcuts.TryGetValue(methodName, out shortcut))
                {
                    rpcFilterByViewId[keyByteFive] = (byte)shortcut; // LIMITS RPC COUNT
                }
                else
                {
                    rpcFilterByViewId[keyByteThree] = methodName;
                }
                if (parameters != null && parameters.Length > 0)
                {
                    rpcFilterByViewId[keyByteFour] = parameters;
                }
                return PhotonNetwork.RaiseEventInternal(PunEvent.RPC, rpcFilterByViewId, OpCleanRpcBufferOptions, SendOptions.SendReliable);
            }
  • Thank you!
  • JohnTube
    JohnTube ✭✭✭✭✭
    Hey @Philipp,

    Did you test those methods?
    And?
  • I'm sorry, I haven't gotten a chance yet -- I bookmarked your reply to implement once I create the second gadget needing this (the old one is currently using the "ask master" type RPC roundtrip). Thanks again for the help!
  • JohnTube
    JohnTube ✭✭✭✭✭
    edited November 2019
    OK.
    Looking forward to reading your feedback.
    Thank you!