Possible addition of "Unreliable" RPCs?
The whole answer can be found below.
Try Our
Documentation
Please check if you can find an answer in our extensive documentation on PUN.
Join Us
on Discord
Meet and talk to our staff and the entire Photon-Community via Discord.
Read More on
Stack Overflow
Find more information on Stack Overflow (for Circle members only).
Possible addition of "Unreliable" RPCs?
ubhkid
2012-02-16 18:29:33
I'm just curious if the subject had been talked about at all. Would be a neat feature to have as I'm an RPC fiend.
Comments
We didn't talk about it so far. It's no problem, we just didn't expose this option. If you want it asap, go ahead an refactor the RPC method chain starting with PhotonView.RPC.
I would like to second this motion!
Unreliable RPC's would allow people to not rely solely on OnPhotonSerializeView for sending serializations, these could change at runtime.
You don't need unreliable RPCs if you want to send unreliable datablobs, just expand the PUN implementation and raise events. Thats exactly what they are for.
RPC is by definition reliable, if its not its no RPC anymore but some overcomplicated way to send data, because the whole point of RPC is to execute a function at a remote point (hence Remote Procedure Call), if the function isn't called for sure or not meant to, you never should have used RPCs at all but just send unreliable datablobs which in Photon are called Events
Your getting stuck on the definition of RPC. I honestly don't care what its called, but a simple way of sending a message to a designated function, which right now is using the [RPC] declaration and .RPC() method, and being able to have it unreliable would be a great addition. I can understand why "RPC"s should always be reliable, but if there is a simple way to implement unreliable RPC's in Photon, and it would come in handy for some users, why not implement it?
I have to agree that unreliable RPCs are against the expectations you (should) have with RPCs. On the other hand, it's technically possible to use unreliable communication for RPCs, too. Cause each player's connection is (independently) unreliable, a call might execute on any number of "other" players: none up to all. In Photon, you can expect this behavior from "events". RPCs are just special (reliable) events you send in PUN and which are used to identify game objects and call methods on those.
I would like to know more about the usecase you think about. Unreliable RPCs would be useless to trigger actions for multiple players. A door might or might not open. At the same time, you certainly don't want to send "door is open" repeatedly to be able to use "unreliable RPCs". As far as I can see, unreliable data makes sense only for position or health or in general: values that get updated soon, so it doesn't matter if individual updates are missing. This can be done by observing a script. Set it to "unreliable" and observe a script that puts relevant data into the stream.
What's your usecase?
I actually have a very specific usecase that came up recently that I needed to create a crazy workaround for.
In my current game, AI players are spawned and controlled by a client. However the control of this AI player can change from client to client depending on certain circumstances. The ai currently uses OnSerializePhotonView to synchronize positions unreliably, but since PhotonViews cannot change ownership, I cannot simply change who is sending and who is receiving for the OnSerializePhotonView callback. If I had the ability to use an "Unreliable" RPC I could simply not use the OnSerializePhotonView callback and just call an unreliable RPC on whichever client is currently controlling the character, and it would send its serialization data to all other players.
What I had to do to work around not being able to send unreliable messages like this, is whenever an AI player is spawned by a player, the remote client who received the network instantiate message would then create a "proxy" controller for this character with PhotonView that is owned by that remote client. Then when a switch of control happens on a character, some RPC's are fired to cause change of ownership and the original PhotonView that was controlling this player is turned off and the proxy is enabled and takes over serializing and synchronizing positions.
As you can see with the addition of unreliable RPC's I could skip this "proxy" step completely and the whole thing would be alot easier.
What you have there is not really a usecase for unrealiable RPC but for View Owner Transfer :) It would be a very good case against unreliable RPCs as it seems that you send quite a bit of data and going with RPCs would be a major performance delta.
Also what prevents you from doing just doing Owner Transfer? Photon is not Unity Networking, you have the whole source of the 'Unity Networking alike layer' right in your unity project and can change this aspect as you see need for it, including ownership handling :)
I do think change of ownership would be a good idea. Considering players can leave at any time and spawned entities from other players who have left become unusable after they are gone.
However I am wondering why RPC's that are sent unreliably would have any more overhead than using OnSerializePhotonView? After looking through the code quickly, it appears that both RPC's and OnSerializeNetworkView end up just invoking OpRaiseEvt with the same arguments, but RPC's are always marking send reliably as true, whereas OnSerializeNetworkView has the option to send reliably or not. The only difference that RPC's and OnSerializeNetworkView appear to have is that RPC's can go to specific functions where as OnSerializeNetworkView always calls the same call back function.
I am probably going to refactor the networking solution just a bit to add one more option for RPC's to send them unreliably, but I was hoping I could stay away from that as I want to update with new releases without having to refactor each time and make sure it works.
Actually porting this kind of changes is rather simple and straight forward. We expanded PUN to have UDP -> TCP fallback (in case the client side has UDP blocked in some form) among other things.
Sure it takes some time upgrading the stuff again but its no day-night difference and nothing compared to porting server side changes ;) Our case just is different in the sense that we don't use the cloud but an own slightly modified LoadBalancing backend
I vote for built-in ownership transfer :D.
Unreliable RPC == "Remote Procedure Suggestion" :ugeek: Just kidding- interesting thread.
I know this is a necro, but a great use case for unreliable "RPC's" is input forwarding for authoritative objects. The built-in unity networking example from Unity's site has an example of this, where the client send's RPC's with their input keys for an object, but the server owns the object, processes the movement and serializes the results to other clients. The only problem with their example is the input forwarding is reliables (RPC's), and is a heinous crime that violates all established standards for network development in fast paced online games. Unreliable is king.
uLink has unreliable RPC's, and it's the only reason I use it over photon (that, and you can write your own bitstreams and send them in RPC's).
Kaiserludi
2012-08-31 13:56:01
@mindlube wrote:
Unreliable RPC == "Remote Procedure Suggestion" :ugeek: Just kidding- interesting thread.
That would be an URPS - Unreliable Remote Procedure Suggestion, then ;-)
Kaiserludi
2012-08-31 14:08:15
@legend411 wrote:
The only problem with their example is the input forwarding is reliables (RPC's), and is a heinous crime that violates all established standards for network development in fast paced online games. Unreliable is king.
You can send something like position updates , that will quickly get replaced by newer info anyway, unreliable, but you should NOT send user input unreliable: Imagine you are hitting a key and send this info around and some clients get it, others not. This would be hazardous for the game consistency. User input is one of the best examples for the kind of data in a multiplayer game, that practically never should be sent unreliable.
@legend411 wrote:
The only problem with their example is the input forwarding is reliables (RPC's), and is a heinous crime that violates all established standards for network development in fast paced online games. Unreliable is king.
Input sending is always reliable, sending it unreliable would be a crime and flat out incorrect as it will completely trash the simulation on the master client / authorative server which is meant to create the one true state of the world, which is plain simply impossible.
Whats sent unreliable is the position update which is actually possible in PUN out of the box as thats exactly what PhotonView Serialization is for. Either to make it unreliable or to make it compressed (both have their benefits). You would not forward the input to the other clients at any point of time, that would totally kill the idea of authorative if everyone is free to do and cheat his own simulation as the idea of authorative and sending the input at all (instead of the outcome of the simulation and save cpu time across the other machines) is to get a correct trustable state. I'm aware that some games do it, most of them are not played anymore in MP as they are cheater flooded though. Not even punkbuster can do miracles and fix absolutely stupid decisions of game devs that though going the cheap way instead of fixing their network flood would be the way to go.
The only genre where input forwarding is an option is MMOs and MMOs are no option for the cloud and PUN
@dreamora wrote:
Input sending is always reliable, sending it unreliable would be a crime and flat out incorrect as it will completely trash the simulation on the master client / authorative server which is meant to create the one true state of the world, which is plain simply impossible.
If you send input keys reliably and there is any packet loss (there will be at some point), the server could get hung up and stuck on old queued up input and the clientside prediction on the moving client is going to be wrong almost indefinitely and he'll just be correcting all the time. The server should use the latest input received, all the time. Glenn Fielder has a nice article that covers pretty much exactly how most modern FPS games networked multiplayer is implemented here: http://gafferongames.com/game-physics/n ... d-physics/
@dreamora wrote:
The only genre where input forwarding is an option is MMOs and MMOs are no option for the cloud and PUN
That's why Quake 3 did it, and every game Valve ever made, and Halo, and CoD :) All using unreliable channels, too.
but these games do not only send these data, they send more data than that. otherwise the position would be constantly wrong as even a 1ms fluctuation on the latency would yield an incorrect calculation. WoW works similar or used to up to the speed hack ;)
Also they are not truely authorative. They are a tricky form of hybrid that requiers pretty heavy cheat protection cause its not secure on its own.
Also its not possible to do this kind of networking in Unity unless you decide to not use collision and physics, cause Unity does not offer the physics simulate forward / backward command from physx, which you would require to apply input in the past to properly get the now state. Otherwise you can not send the current position of the object through the network to get it in sync from time to time, at least not if it takes longer than the setback time you apply for any command in the client side prediction
And naming all these games is funny cause torque actually sent bit optimized positions not input and as far as I'm aware, torque / Tribes still has the by far best networking code ever used in games. Tribes 2 hosted 256 player games in the days of 56k modems, something valve, dice etc do not even manage on 20mbit+ lines today, they can barely manage to pull off 32 players without entering trouble. And none of todays games aside of tribes ascencion is even remotely as fast as tribes used to be :) (slide & glide speed and low latency requirements >>> Q3 rocket bunny)
Just facing the same issue as the OP.
Currently we got players who are invisible and do not sync their positions at all. We instanciate AI (position sync'ed) that can be attached to a player and follows it.
Problems are:
- PhotonView can got only one owner and we can't change it on the fly
- destroy/reinstanciate to change the ownership is not our will
- the player can't send new bot's position because he has no access to "stream.isWriting" since he is not the owner of the Photonview
- RPC are not a good option because using reliable sync for position is madness
- Unreliable RPCs could have been an option in the general idea because it would be a nice workaround
How could I do this please?
As said before, refactoring Photon's code would be pain to manage since we want to stay up to date.
Apart from that, imagine a strategy game where units are shared between several players. Is this possible with photon? We currently can't have multiple owners.
Thank you.
PS: I'm using PhotonCloud (with PUN). PPS: I will take another look at Operations and Events. This part of the documentation was not clear enough for me (so do Lite/MMO/Loadbalancing "types").
I don't think unreliable RPCs are actually solving your ownership issues. The big problem there is: You need to switch the owner in a synced, consistent way, despite random lag and leaving players (for 3 and more players). If at any time 2 users think they own a unit, either could kill it (worst case) and your state is broken. Sorry I'm not a help really but I know I can't solve this in limited time in a general way.
To dig into Photon, concentrate on the LoadBalancing API and server application of the same name. It's Photon Cloud compatible. LoadBalancing is actually using most of the naming and basic features implemented by Lite but doing more and with multiple servers. Ignore the MMO stuff. Events are what you really need to grasp. Then you can send whatever you want between players. Properties are also good to know for semi-persistent info (like of a player).
Definitely going to look at the API! Thank you again.
MoPhoGames
2014-01-09 19:31:17
@dreamora wrote:
but these games do not only send these data, they send more data than that. otherwise the position would be constantly wrong as even a 1ms fluctuation on the latency would yield an incorrect calculation. WoW works similar or used to up to the speed hack ;)
Also they are not truely authorative. They are a tricky form of hybrid that requiers pretty heavy cheat protection cause its not secure on its own.)
Not true. Source Engine is fully server authoritative. As far as position updates, clients ONLY send input state and nothing else. The reason latency is rarely an issue is because essentially sending a frame of input is a single frame of simulation. Imagine it kind of like the way DOOM networking works - you wait to receive input before you advance the simulation by one frame (except instead of the entire game, it's just one character on the server). So every frame the client sends input to the server, which responds by advancing your player's simulation by one frame. If you don't send input, or it gets delayed, then it gets delayed on the server too. It's because they are server-authoritative that rubber-banding exists in those games. It's because the client's local prediction is too far off from the server's state, therefore the server sends the true game state to the client (causing you to snap - Source engine hides this by smoothly interpolating). If packets are dropped, this can happen (luckily, packet loss is not very high these days - usually Pingtester.net sends and receives all 200 or so UDP packets with 0% loss on my network). Actually, in this case having reliable packets can lead to serious exploits - someone only needs to stop sending packets, move to a new position, and start sending packets again (packets that would be send while they are moving are buffered up, and all sent at once when they reconnect) - now you've got to deal with "lag-steppers".
On topic, I can think of a good usecase for unreliable RPCs. I have a voicechat system which is supposed to plug into any networking backend, including Photon Unity Networking. Voice data is not really a good candidate for using OnSerialize, so it's better to send over RPC (data is not constantly sent - if the user isn't speaking, for instance). It would be awesome if I could just send this as an unreliable RPC.
If you don't have anything to send in OnPhotonSerializeView, just don't write anything to the stream and nothing is going to be sent. It even provides a good way to regularly check the voice buffers for stuff you need to send (instead of starting another coroutine to check and call RPCs).
Back to top