Syncing health and attributes with onchange?

Options
So, currently we sync our objects with transform data via OnPhotonSeriaelizeView using Unreliable On Change. This works well. However, it seems like on change is only triggered when transform data changes. We put health in there and assumed when health changed it would trigger it, but thinking about it now, of course it didn't work. So how do we add/change what can be watched for changes? Our game server has control over health and attributes but we have to use RPCs to update these things so we're not constantly sending that unchanged data or the network. Is there a way to do this built in to photon? I'm not a fan of sending the string name of the method every time we need to update health when it could just be a small int sent when needed. Our RPCs are string names + dictionary parameters + whatever Photon tacks on. It's bigger than it needs to be for a health update.

Comments

  • Tobias
    Options
    Only the owner/creator of a PhotonView is sending updates. There is only one client which is writing in OnPhotonSerializeView.
    If you add health as one of the values to the PhotonStream that's sent, and if that (or any other value) changes, then the update should be sent and the others should get the new health.
    The problem is maybe that the "server" can't sent data for objects it doesn't own?!

    Do you have a "X hit Y with Z damage" RPC? If the "server" is sending that anyways, you can reduce the health based on that hit info. Each client will then update the others that health was reduced.
    Alternatively you could make the "server" send health for all clients in a single RPC or via OnPhotonSerializeView. The others just have to apply each update.

    RPC names are replaced by a much leaner byte-code, according to a RCP list stored in PhotonServerSettings. As long as you keep your own update info minimal, everything should be fine.
  • Right so our current setup is an instance of unity running on the server (spawned as needed on a gameserver when a new match is requested). This "master client" manages 99% of our game data--the exception being player movement, as we haven't bothered with the prediction stuff just yet to keep controls responsive. If a player shoots an object it raises an event to Master, which authorizes the action, modifies members as needed, and then calls a standard "UpdateInfo" RPC to PhotonTargets.All which we use to accept a wide variety of information for syncing. However I'd like to not use the RPC every time info is updated. It's a lot of calls. Every time something is shot and should take damage this RPC triggers. In a large firefight this could be hundreds of calls a second. I'd much rather leave the event raising as is, and have health and modifiable attributes sent with the stream. In our early tests however, the only thing that would register as changed was transform information. Sticking just health in OnPhotonSerializeView wasn't enough to get it to execute. It is possible there was something else wrong, but when we added some transform info to that method it would work and if we took it out it would stop working. Perhaps a coincidence.

    So, to be clear, everything works as intended right now. I'm just trying to optimize things. Any thoughts, or is what we have sufficient? And this is a shooter style game (of course, since that's all anyone makes these days), which is why hundreds of calls could be made in a second. One call for each detected hit.
  • Tobias
    Options
    If the players own their characters and send their position, then no one else is able to send anything via those PhotonView on the character. Not even the server-unity-instance. In that case, it won't matter what the server-unity-instance tries to send, it should not go anywhere if you don't control the PhotonView.

    If might be oversimplifying things but it sounds like you rather want to send less hit-updates in probably a fixed frequency instead of doing it brute force and sending each individual update.

    It definitely makes sense to limit the number of updates and make them independent from the action that's going on.

    You should be able to aggregate hits for 100 ms, then "write them down". The hitpoints per player is only the current value instead of being sent with each hit. In fact, maybe you don't need the hits individually and just send "who killed who" as a summary, when you detected any kill.
    Send this with any PhotonView owned by the server-unity-instance. You could do this in an RPC or you can use an observed script. An observed script gives you the benefit that the frequency for OnPhotonSerializeView is already built-in. You can re-use that.
  • Ok, we've deviated from the original question quite a bit.

    here's some pseudo code off the top of my help to help explain what I'm asking.
    [code2=csharp]void OnPhotonSerializeView(args...){
    if (stream.isWriting){
    //write transform data ... if it changed? If transform data changes, but health does not, will health still be sent with the stream or omitted?
    //write health ... if it changed? If health changes but transform data does not, does transform data get ommited from the stream?
    }
    }[/code2]

    This is all I'm wanting to know. If I can forgo sending an RPC at all to update health, that would be cool. But what I don't want to see is (let's say health is 50) 50 getting sent every time the player moves, even though health hasn't changed. Likewise, if a player is standing still and gets shot, I'd like to see just health get sent and not transform data. Or, should I handle this on my own? Save last update's state and if any member differs from the original add it to the stream?
  • Tobias
    Options
    PUN can only handle delta compression to a degree. It does not know which values are related.
    In reliable delta compression it looks up which individual values are changed in the stream and doesn't send unchanged ones.
    You could use 2 different PhotonViews. One reliable delta compressed for state values and one "unreliable on change" for positions and rotations.
    Or you can do it yourself, of course.