Best way to implement an interactive scene object?

I'm trying to implement a scene-owned object, a CTF flag specifically, that has a synchronous state on all players. How can I go about doing this? I can synchronize movement with a FreeMovementMotor but at some point I need to turn the renderer off- this can be accomplished using RPC calls however, for example, if a player joins the room after the renderer has been turned off through an RPC they of course see the gameobject with the renderer still on.

I could do some wierd thing where some client already connected forwards the state of it when a player joins but that seems like a really roundabout way to do it- shouldn't the scene object be responsible for sending its own state, not some other owner?

Besides a CTF flag I need to implement a lot of other scene owned objects that all need synchronized states, is there any system in place to handle this?


  • Sorry, this topic has been neglected for a few days.
    If I'm not mistaken, neither Unity Networking, nor our re-implementation offer a great way to implement these things.

    We do have "properties" for rooms and actors but we are yet to expose them in PUN. Those are what you are looking for, with a bit of organization:
    Properties are a Hashtable with key-value pairs and they are buffered server-side. They can be updated there and pass an update event at the same time to the clients currently in the room. Also, new players get them on join.

    The properties are not per item/photonView but a lot better than sending updates when someone joins.

    Give us a few days to implement them. We would like to get your feedback on them then.
  • I ended up using some custom ops/events on the server to keep track of them since I have a deadline coming up soon but thanks anyway. I was also wondering, are PhotonViews intended to be used on scene-owned objects or just player-owned ones? I tried one on a scene object set to observe a FreeMovementMotor and had one player move the object but neither object seemed to send or receive the stream events.
  • For future use:

    Interactive scene objects / Switching ownership of an object/player/whatever.

    1) use RPCs only and manually keep track of ownership.
    The easiest setup would be to use an RPC to decide who is the owner (e.g. send: SetOwner(ME))
    When I am the owner, in an update loop do whatever actions are required (make sure not to send RPCs every game frame..only about 10 times per second or so).
    However, OnSerialize will not work as desired (meaning that the PhotonView Observed target will also not work properly) OnSerialize/Observe always use the owner of the PhotonView as the one who can write/send updates from this PhotonView.
    If you send a lot of messages you'll want to use OnSerialize instead of RPC messages as OnSerialize is optimized for a lot of messages where RPC is not.

    2) Switch the owner of the PhotonView.
    By switching the owner of a photonview the observed property (and OnSerialize function) will automatically work as intended. To do this the PhotonViewID will have to be reapplied though.

    The new owner would allocate a new ViewID. This player will send out this PhotonViewID and every client will have to set the PhotonView's viewID to the new one.
    void MakeMeTheNewOwner()
            PhotonViewID newID = PhotonNetwork.AllocateViewID();
            photonView.RPC("SetNewOwner", PhotonTargets.All, newID);       
        void SetNewOwner(PhotonViewID newID)
            if (photonView.isMine)
                PhotonNetwork.UnAllocateViewID(photonView.viewID); //Recycle this number (we "only" have 1000 views per default)
            photonView.viewID = newID;   
            // TODO: This code works fine if we have a game where no other players can join while a game is in progress. 
            // In other games we have a problem: new player joins it will not be notified of the new owner.
            // I think we can't simply buffer the SetNewOwner call as it would be called several times (possibly the wrong order?).
            // Furthermore we do not know if this GO was instantiated manually, using PhotonNetwork.Instantiate or whether it was a scene object.

    Please note the TODO in the code, the above code is not solving all situations yet.

    We should probably add a PUN function which solves all of this, e.g.: PhotonNetwork.SetNewOwner(targetPhotonView, newOwner);