Sending Input [Photon Cloud]

Options
Obatztrara
edited February 2012 in DotNet
Hey guys! :)

I started with Photon Cloud yesterday and it is working great. I have implemented simple matchmaking and synchronization between the players of my RTS. The next step is input.

For my RTS to work I need to send every players input to all players, who then each calculate the (deterministic) simulation on their own. This should be as fast as possible, else the delay will interrupt the game flow.

On my end I can easily parse the input into arrays of bytes or somethign similar.

Now, I have no idea what the fastest and safest way of sending these bytes would be. Any suggestions are welcome. :)

Comments

  • Kaiserludi
    Options
    Hi.
    You would use LoadBalancingClient::opRaiseEvent therefor. You can either sending just byte-arrays or yalternatively you could also send whole Objects, when registering methods for their seralization and deserilization via Photons customType interface.
  • Alright. For now im setting the whole thing up with RPCs, just to get it working for a moment. As soon as that works I'll look into what you suggested. I'll report back then!
  • Ok I have it working with RPC's, with some problems though.

    1) Could you (or someone else) explain a little what the advantages of LoadBalancingClient::opRaiseEvent in comparison to regular RPC's are? Keep in mind I just started with Photon (and Networking pretty much) two days ago... :D

    2) Regarding a problem I have with the RPC's. My game runs in fixed intervalls. All input is recorded, send to all players in the game and then executed at a later time. This is to ensure that everything stays deterministic between players.

    Sometimes an RPC will arrive too late, which means that the Input is already executed on the other clients and has to be discarded.

    So: What's a good way to determine how long it takes RPC's to reach all players? This would be the absolute minum I have to wait before starting to execute Input.
  • Tobias
    Options
    I'm glad to see you're trying Photon! I saw your posts on the Unity forum but didn't want to come across as hijacking your question with ads.

    For reference: We have two different client frameworks that work with the Photon Cloud. One is the "Photon Unity Networking" package available from the Asset Store. The second is included now in the Unity Client SDK from our download page: www.exitgames.com/download/photon.
    Both make use of the same servers and features but they are different:

    a) PUN is a bit more indirect and "Unity styled". It uses components (PhotonView) and scripts to access the data you want to sync. This is best if you don't plan to rely on the server for logic. Photon Cloud passes-through information but doesn't work with it. It works with RPCs (from client to client) and authoritative work is done mostly by a "master client".
    The "plain" loadbalancing API from the client SDK is more geared towards programming. You should familiarize yourself with Photon's features more directly and it will help if you understand what an Operation is and how it is used to create events to pass data from A to B. This will give you more insight and gets you closer to the point where you program logic on the server and extend it for your game.

    b) PUN creates objects and IDs are assigned and maintained. These must be passed all the time, no matter if this is necessary or not. Each RPC has a little overhead.
    The client SDK gives you more direct control of what you send and how you identify items across multiple clients. It doesn't have RPCs but sending your data in events is as good and with less boundaries.

    Each comes with source, so you could adjust either when necessary.

    About your questions:

    1) RaiseEvent is used by RPCs. RaiseEvent will take a hashtable you compose and an "event code". The receiving players will get the code and event-content and you program the reaction to it. Apply the values, call a method, change a state.
    RPCs are built on top of that and use it to call a method by name. They are simply a level higher up.

    2) I think you will need to make sure you don't skip stuff cause it's late. This will kill your determinism, right? Or you need a way to skip the step for the originating player. But most likely it's in the simulation already.
    Aside from that, you can roughly assume that the roundtrip time is needed to pass a RPC from client to client. You could exchange the rountrip time of all players and average it, if needed. Use PhotonNetwork.GetPing().
  • First of all thanks for the detailed answer! I have already decided to use Photon Cloud, since it suits my needs 100% (non-authorative relay server).

    1) Regarding RPC: I have the problem that I need to know for sure if a RPC reached its destination. For now Im sending another RPC back, just to confirm this. Is there a better way?

    2) Is pretty much solved. I have a Controller that makes sure all network events are received and confirmed. It pauses the complete simulation if anything is missing, kinda like Starcraft 2 does (Player XY is lagging, kick in 60 seconds). Its inefficient (see 1)), but it works.
  • dreamora
    Options
    1) RPCs are guaranteed to be received so you don't need a verification that it reached it (they are reliable ops). If it does not reach the target its a bug that needs reporting.
    Sounds more like you are interested in when it is received, not that it is received.

    The SC2 comparision fails cause SC2 works quite a bit different in this aspect, the pause triggers in when a player times out there, not when a single op is not reaching its target. I'm not even sure to what degree it sends stuff reliable, already simply due to the koreans and the flood they would generate with reliable ops and their apm ;)
  • No, it works the same. If a single command wouldnt reach its destination the complete game would break. SC2 is 100% deterministic. Early beta still had out of sync errors from time to time, also the replay file size kinda proves it. Theres more but Ill just name these two as an example. It has to stop the simulation both when a player times out or when a command didnt reach its destination, else everything would get out of sync.

    1) You hit the jackpot with this one, though. If there was a way to retrieve the received time from an RPC that would be awesome! Do you know if thats possible?

    Edit for fun: About the koreans. Lets say the average korean has 300 APM. That would be 300/60 = 5 actions per second. So thats 5 really small RPCs, small since they just include the input. That really shouldnt be a problem, bandwithwise...
  • dreamora
    Options
    1) Unluckily that requires that you send back an RPC as the OperationResponse only would work from the Photon server itself, not the master client, as such the only way to get the time of reaching the target is making the target send back a packet with the network time of reception hence the RPC path is pretty surely the right thing to do here.

    BUT: The SC2 analogy brought up a different thing that needs to be cleared and that might lead to a totally different approach - how do you handle master client leaving and handing over the session to a different client?
    I ask because depending on that you might potentially want to consider to implement GameProperties and ActorProperties to make use of them as they are 'temporally persistent' (means they are persistent but only for the lifetime of the room / actor) on photon itself, not on a client, hence they would automatically remain present in case the master client gets lost, instead of relying on RPCs and potentially buffering only.

    SC2 - deterministic: I don't see the problem here. The commands aren't sent as 'delta' informations where 1 missing packet = incomplete data (unlike WoW where the famous speed hack was a direct consequence of some lazy implementation on that end) but as absolute informations so you don't get 'jumpyness' if one packet is missing.
    Question really is what SC sends, only the target point of orders or intermediate orders as the AI calculates them (unsure if the AI is 100% deterministic over different clients due to latency + local actor avoidance + non-uniform actor radius. For stuff like build orders, attack and abilities the guaranteed reception naturally is a core requirement, no question. But movement orders make up the major bulk of data sent I would assume)


    For Fun: yupp mixed up some math due to visualizing the stuff in my head that you see on videos instead of doing 'dumb maths' ... Eye and processing of visual information are still 'simply stupid' at times.
  • Alright, so I'll have to use RPC's for the confirms, thats a bit of a bummer, but oh well.

    Regarding the masterclient: Currently all my clients are 100% equal regarding game logic (Cloud!). I haven't really done any testing, since Im still trying to get more important features running, but in theory if a player leaves that shouldnt cause the network to behave differently (just without that player).

    Sorry for the noobish question, but: What makes the master client special?
  • dreamora
    Options
    The master client is the one opening the room.

    All messages you sent with RPC Target MasterClient are sent to him.

    The idea behind it is that hte master client is the owner of the game and the decision maker. Its the 'cloud attached server' or 'simulation node' if you want to call it like that, where as the MMO and Lite photon instances use photon directly as server.

    If you hosted your own photon server with load balancing instance you could even make it a client running in headless mode on your server for example (for shooters you would call that a dedicated server then, for RTS there are only few games that know such a concept. Primarily World in Conflict to my knowledge)
  • Tobias
    Options
    The "master client" is always the one who's in the room for the longest time and thus has the lowest player ID (actor number). The creator of a room is the first master client, too.
    It can switch if the master leaves, so if you assign a special role to that player, make sure you either cope with the switch or make all players quit as well.

    Oh. And you maybe don't need to send a RPC exclusively to confirm something. Each player is sending input all the time, so there should be room to put in some more data like confirms. This will reduce message-usage, which will be one of the factors for our pricing.
  • Good Point. I can probably group all messages of say 20-50 ms into a single rpc... It cant be too much, else it'd increase the lag too much.