Great Net Engine! Have some questions though :)

Options
Hi,
first of all, thanks for Photon, it's awesome to work (and play!) with. I have worked with some other network engines for different gameengines before, but photon for unity is by far the most easiest to use. Writing netcode is actually fun now :)
Also, free Photon Cloud access is a real timesaver and makes it almost way to easy to get started.

After toying around with it for some days, i have some questions though:

1.)
I'm basically using the supplied code from the PUN Documentation for the PhotonView Component to pass data around between clients
void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info) {
    if (stream.isWriting) { //We own this player: send the others our data
        stream.SendNext((int)controllerScript._characterState);
        stream.SendNext(transform.position);
        stream.SendNext(transform.rotation);
    } else { //Network player, receive data 
        controllerScript._characterState = (CharacterState)(int)stream.ReceiveNext();
        correctPlayerPos = (Vector3)stream.ReceiveNext(); 
        correctPlayerRot = (Quaternion)stream.ReceiveNext(); 
    }
}
This is for very basic player movement and obviously doesn't create too much net overhead.
Now what if i want to add additional interaction methods for the player, like attack, casting spells, trading, whatever? The streamsize would increase. As far as i understand it, if ONE value of the stream changes (player position/rotation, isShooting, isCasting) the whole stream has to be sent over the net to update the changed value on all clients. Depending on the number of playerattributes/values, this could cause much unnecessary stream overhead.
My question is, would it be a good idea to use some kind of bitmasking when sending streams? Like so:
void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info) {
    if (stream.isWriting) { //We own this player: send the others our data
        - create a bitmask depending on changed player attributes/values which should be send to the other clients
        - send bitmask
        - for each entity in the bitmask, send it's coressponding data
    } else { //Network player, receive data 
        - get bitmask
        - get data according to bitmask
    }
}
Is this a good method for reducing stream/net overhead, or are there better ways? Is this even needed at all or does Photon handle unchanged values internally and doesn't even send them at all?


2.)
Let's say there a 2 gamerooms. Room A has 2 players, room B has 3. If a client sends data in room A via PhotonView Observers, do clients in room B internally recieve it, but simply don't use it? Same for RPCs. I'm asking because of this:
5.3.2 Groups and Scoping
The PhotonNetwork plugin does not support real network groups and no scoping yet.
While Unity‟s “scope” feature is not implemented, the network groups are currently implemented purely client side: Any RPC that should be ignored due to grouping, will be discarded after it‟s received. This way, groups are working but won‟t save bandwidth.
The way i get it, this only applies to client to client communication inside one room, but i want to be sure.


3.)
I'm currently coding everything within Unity/Mono for rapid prototyping, haven't touched servercode once. Somewhen in the future (we are talking about years here) i might need to port parts of the code to the Photon Server for security reasons (which is, i guess, pretty lousy right now due to the pure client side implementation?). If i want to move code from unity to photon server, i would have to port the function in question from unity to photon server, then make a call from unity to the server calling the function and pass the result (if there is any) back to unity. An example would be attacking: Only send player input to the server, then let the server decide if the player was 1.) able to shoot 2.) did hit something. How would i do the function-calling-on-the-server-via-unity-and-passing-back-some-data part (I'm not talking about porting from unity/mono to photon server here)?
If it's too much of a hassle to explain, don't worry. I'm far from porting code to photon server and only asked out of curiosity :)

4.)
I know this topic has been discussed before, but i want to make sure:
There will be lots of NPCs/Enemies in the game. What's the best way to send npc data to the clients?
1.) Attach a PhotonView to each NPC. I guess this is a bad idea.
2.) Extend the bitmask idea from above and send an ID first, then the bitmask, then the actual data. ID will be used to determine which object the bitmask and data belongs to. Then use a SINGLE PhotonView Component for all NPCs. This might be better than 1.), but sending over the ID and bitmask alone everytime would create quite some net overhead...i guess (again! :D ). Also, sending data from two or more NPC at once isn't that trivial anymore, which isn't all THAT bad as you could then simply pass the data one after another and forget about the small lag. If there are LOTS of NPCs at once on the screen though, you might get in trouble.
3.) Let the photon server handle all the NPCs. If a player creates a new room, server will create all the NPCs. Also, no problems if the master client changes. Might be the best choice ... Apart from handling all the other stuff like for example physics and world interaction in general plus reduced workflow as one would have to code in unity and server simultaneously. This might be the best choice (from a technical view).

Well, thats it for now. But don't expect me to not ask other questions once these are answered :lol:


On my next trip to Hamburg, i'll bring along some cake for you guys.

Comments

  • dreamora
    Options
    2) No, communication is exclusively within only the room, the rest does not even exist for ya

    3) yes thats possible. Examples of that exist in various cases, cause every single operation gives a result, normally its just limited to 'fine' or 'failed' but you can pass whatever.

    But you would not do the shooting through request and then fire cause thats 2 times forth and back so 4 times the lag to fire. Big no go. Instead you let the client predict the time when he is able to fire again and then he fires and the server verifies upon shoot request that it really is fine and if not gives a failed result

    4) the point of onserialize is that you have a view on each serialized objects. You can't send an unlimited amount of data, there are size limits. even worse is that you can no longer make use of delta if you don't send 'confined, limited changing data'
    As such I would definitely go with 1 view per npc and use delta syncronization.
    Also at 30-50 npcs (I doubt you are targeting for more, cause then you will have other problems to fight)

    As for npcs on the server: you have to implement all yourself. if the master client does not simulate them this includes a world representation and replace the physics on clients by the same you use on the server
  • Tobias
    Options
    1. Like in Unity Networking, you would usually send RPCs for actions like "shoot".
    I'm not sure if bitmasking is necessary in all cases.
    Depending on your experience level, you shouldn't try to optimize everything from the start on. It's worth avoiding too much data but if optimizations keep you from developing your game at all, try to get started and then learn along the way.
  • Thanks for your answers so far, they were really helpful :)
    2) No, communication is exclusively within only the room, the rest does not even exist for ya
    Nice, so i did understand it correctly. Good to know or sure :)

    But you would not do the shooting through request and then fire cause thats 2 times forth and back so 4 times the lag to fire. Big no go. Instead you let the client predict the time when he is able to fire again and then he fires and the server verifies upon shoot request that it really is fine and if not gives a failed result
    I hastily put together a bad example. Should have thought about it some more. Thanks for the hint though. Sending only input really is a bad idea in this case.

    4) the point of onserialize is that you have a view on each serialized objects. You can't send an unlimited amount of data, there are size limits.
    Well i would not send ALL data for ALL NPCs at once, but rather go through some kind of loop for all NPCs which have changed values and then update these. So size shouldn't be much of a problem (but the resulting lag of this method would). However this:
    even worse is that you can no longer make use of delta if you don't send 'confined, limited changing data'
    might become a real problem in this case. I did a search for delta en-/decoding. The way as i understand it, you send ALL data at the start, then send only the changed bits. Now if my data stream is a different one every time (as there a numerous npcs) delta encoding obviously would not work anymore, as all data would be streamed again. npc1 has different data than npc2, so if i send npc2 first, then some changed value for npc1, all data would be streamed for npc1 as it would be completly different to the datastream before. So as a result: delta + bitmasking = very bad idea. Please correct me if i'm wrong.

    As such I would definitely go with 1 view per npc and use delta syncronization.
    Also at 30-50 npcs (I doubt you are targeting for more, cause then you will have other problems to fight)
    I thought the PUN manual said it's bad pratice to have multiple PhotonViews in one scene/room (except at least on PhotonView per Player). Have to read that part again.
    The game itself is a coop PvE game with a max of 8-16 players (will start developing for a maximum of 8 players, then see how it goes). Currently it's planned like this: The player who first "sees" an npc will take over it's gamelogic and datastreaming. This way if all players are at different parts of the map, the master client wouldn't have to process ALL npcs. Instead all players would process npcs for themselves. Another idea is to share npc around: 1st "seen" npc goes to player 1, 2nd to player 2, ..., 9th to player 1 again, and so on. If a player leaves the npcs "belonging" to that player will be shared between the remaining players (if they are currently in range of the npcs in question).

    As for npcs on the server: you have to implement all yourself. if the master client does not simulate them this includes a world representation and replace the physics on clients by the same you use on the server
    Yes. As already stated: way too much work during the prototype phase with only myself developing the game at the moment.

    1. Like in Unity Networking, you would usually send RPCs for actions like "shoot".
    I'm not sure if bitmasking is necessary in all cases.
    Depending on your experience level, you shouldn't try to optimize everything from the start on. It's worth avoiding too much data but if optimizations keep you from developing your game at all, try to get started and then learn along the way.
    Well i'm just trying to understand how Photon works so i can avoid obvious mistakes :) Asking these questions made me search for delta encoding and now i have a general understanding on how that works (at least i think i do, see above) and came to the conclusion that bitmasking is a bad idea if i want to make use of delta.
    As for learning along the way: I'm creating this game as my master thesis. The purpose is to have a look at new/alternative ways of gaming. Also user generated content will play a big role. Additionally i never dealt with npcs in multiplayer games, so far there were always only players interacting with each other. So there will be plenty to learn and do wrong along the way and i'm thankful for every mistake i can avoid :)