A Unity ID allows you to buy and/or subscribe to Unity products and services, shop in the Asset Store and participate
in the Unity community.
Discussion in 'Multiplayer' started by RevenantX, Jun 30, 2016.
@TriangularCube yes there is no such method because it rarely used) I will add this)
Added to master branch.
Hi there. Quick question, does LiteNetLib use any encryption? Thanks.
No there is no any encryption. If you want use encryption - use already existring encryption methods from .net to information that you want to encrypt.
Yeah I just wanted to say this is awesome man. This deserves more recognition. Really great work. And thank you for leaving it open. I've read through the UNet HLAPI source since it was in beta and there's some great concepts in there but the overall project is lacking including those issues that arose with the transport layer. Your solution provides a transport layer that I can extend if wanted and essentially build my own higher level system on top of as I see fit (and can borrow ideas I picked up from the HLAPI), which suits me perfect. I forked off GitHub, your code is clean as S***, I love it. Thanks again and awesome work man. That's all
Heard a lot of good stuff about your UDP lib, currently adding it to the MLAPI, it's essentially an alternative to the HLAPI for handling high level stuff, and i'm making the transport modular. I'm just wondering if the Ping is one way travel time or if it's the round trip time? I need to use it for the built in lag compensation. And also, what unit is it in? Since it's an int i'm assuming milisecond. Is it an average or based on the latest message?
Secondly, is there a network timestamp feature like there is in UNET and Lidgren?
@TwoTen hi! Ping in my library - is average RoundTripTime in milliseconds
Alright, What about the Timestamp feature? Is there such a thing?
@TwoTen no, there is no timestamps in packets
Are there any plans to add timestamping or a way to get the last RTT (for reliable packets). Either timestamping or just adding a peer property giving the last exact RTT.
As far as I know OnNetworkLatencyUpdate gives you the last exact RTT.
@wobes no. OnNetworkLatecnyUpdate called every second with average rtt too.
@TwoTen well i can add this as option.
Yes I need that for Lag compensation. Thanks a lot!
I am working on 2 player multiplayer game in Unity.So I need peer to peer communication. Is it possible without using any master server.
I need that to connect user behind NAT also. Could you please provide me working script for Unity which is Using NAT.
Because I am not getting how user will find other user if both are behind NAT.
Thanks in advance.
for NAT hole punch you need master server.
Suppose Both peers knows external and internal IP of each other and both are behind NAT. Is it possible to connect them without Master server.
I'm sorry if this question seems stupid. But I feel that should Possible if both peer having all info of each other.
@jogidipen then try connect directly from both sides simultaneously using known public ips and ports.
could you please provide me sample code exactly how to implement this? Are you sure by connecting it through only public Ip it will work if Device is behind NAT?
Just want to make sure my understanding is right. The default logic thread sleep time is 15 ms and the ipv4 socket has a set send buffer size of 1024 * 1024. Adjusting the sleep time(update interval) allows this buffer to be filled as calls to the Send methods take places in that period correct? Then buffer is flushed and we rinse and repeat?
Great work on this library Rev! I like it's simplicity - it can be tailored easily to custom projects.
+1 for getting last RTT.
Not sure. Better use master server (you can use some cloud for example DigitalOcean for 5$ in month). There is example in github of NAT punching https://github.com/RevenantX/LiteNetLib/blob/master/LibSample/HolePunchServerTest.cs
Socket buffer used internally in OS.
My library sends packets every UpdateTime milliseconds.
It sends all pending Unreliable and Sequenced packets.
And maximum 64 Reliable and 64 ReliableOrdered pending packets (because of window size).
And if MergeEnabled = true then it will combine small packets to one bigger (to MTU size)
So in most cases socket buffer will not be overflowed.
You can use Flush() to send this packets immediately.
This thread sure looks dead, but I have some questions regarding the architecture.
I have built my space game prototype to the point where I am ready to implement my real time features.
So far, I have several screens on the client, from which I am able to send some requests to the server. In the code where I handle the requests on the server, I communicate back to the client some information, then I update the UI accordingly on the client.
This works well, but I got a bit stuck. The client sends a packet to "start" the real time battle, I send the response from the server with all the relevant data to instantiate the "battle". Now, my problem is I don't understand where the server should contain the game logic for my battle.
My Run function on the server is exactly like in the examples, it's a while look which calls PollEvents() and Thread.Sleep(15). Should my server iterate through all connected clients and send requests based on some logic inside that same while loop? How can I create non blocking timed events on the server to inform the client that something has happened after X amount of time, without the client initiating some sort of request?
I am willing to provide more information if it's still unclear. Perhaps I am on the right track but I wonder if there are any easy techniques I could use to implement my realtime battle with this library.
I looked for your timestamp approache, and find you use a ntp server.
This can't work on local network without internet no ?
Why don't provide a network Timestamp like in Unet library ? Will be so cool.
I Don't know how to do such things however
We don't use any outside timestamp or time sync features like NTP for our game.
To keep objects in sync over the network (like elevators that periodically go up/down, moving platforms, even NPC with predefined routes, ...) we have a TimeSync class that implementes a syncing algorithm to get accurate time synchronization over the network. It only takes 3 messages to get the server-time-offset accurate to below 0.5ms (of course it also depends on latency jitter, but that's rarely an issue).
If @RevenantX thinks it's a good idea, I'd be willing to contribute that to the library.
Most of the time games really only need a very closely synced "timer", instead of the knowing the absolute time.
For messages like "someone shot a missile exactly 0.084 sec ago" or simply keeping the movement of platforms in sync (assuming they do something like posY = Mathf.sin(networkTime); ) that's perfect.
@RevenantX I got a question:
Are there any plans to implement "channels"?
Like multiple network channels for different stuff. One sequenced channel for health, one for mana, one for....
Also are there any plans to add some handling to ensure that at least one of the latest packets arrives (a half-way thing between reliably and unreliable, to guarantee that at least some changes are received by the other peer).
Because with the nature of unreliable messages people often just spam updates, but you can never be sure that even one message arrives. And if all the (lets say) health packets went missing somehow, then the game will continue but with the wrong health displayed for one player. Some network libraries I've seen sometimes (every ~3sec) send a sort of "checksum" (1 byte per used channel) to ensure that the latest message in each channel isn't at least way too old (so at least one of the last 10 updates).
Stream-based time synchronization with samples accumulation? Which timer mechanism used for this?
Only works if the system actually supports high precision timings though.
Almost all "common" combinations of OS + CPU do, but for those who don't you're obviously out of luck. Accuracy up to +-30ms is the best you can hope for then.
Tip for anyone not aware and asking themselves "why not DateTime?"
Because it usually only increments in 15ms steps
It will no longer be synchronized as soon as lag/freeze occurs on the server/client and this is the problem of any time-based synchronization techniques. Stopwatch timer doesn't guarantee to act as a monotonic time and should be regularly resynchronized (every 1-5 minutes) depending on requirements.
Many algorithm rely on deltaTime between server and client, example : Timer (haha basic...) or position synchronization...
If there is an other way to know the delta time between server and client, tell us
There are several well-known techniques, one of them is ticks tracking that used in Quake 3 networking model.
When there's a lag spike large enough for things to get noticeable out of sync, then the timer not being accurate at that moment isn't much of a problem, no?
Can you elaborate a bit more? What situation did you notice problems with in the past? I don't think I can follow that argument, the stopwatch is based on hardware timestamps, so any sort of lags or freezes will not somehow go out of sync.
Next time you query the stopwatch, you get the correct timestamp...
The only actual problem is that the time starts to drift eventually because DateTime and stopwatch use a completely different internal mechanism (stopwatch using CPU ticks which has more precision, but is not as accurate and will slightly, drift)
I read for ticks and 1500 archers.
It's used for RTS with many AI and full deterministics games. No more for fps, and whatever games that don't want to be "lock stepped".
Maybe I'm wrong, there is not so much documentation when you dig into game development stuff
Is this p2p or server autoritative?
Neither, it's an UDP library.
You're talking about high-level mechanisms to control games, which is something different.
You can build whatever scheme you want to on top of this.
That's why it doesn't work for multiplayer games. Hardware is different, and it's not perfect. You will get different timing results on different multi-core processors. QPC, as well as RDTSC instruction, is not a reliable source of high-resolution timing on different machines. Synchronize the time using your current implementation based on Stopwatch timer and play any modern game with three or more players and after several hours you will see how easily time gets out of sync.
ECS comes to solve most of your problems with it.
You can know the tick frequency of the processor so different speeds are not an issue.
As for drifts: Yes, there are some very minor differences in speed, even after accounting for different frequencies; But that's why we simply keep re-syncing over time (sending packets every ~20sec to determine how far the timings have drifted apart and if we should do one more back/forth cycle to bring it together again).
For our purposes we want the time difference to be accurate to about +- 32ms (so ~2 frames).
And with this mechanism, under usual/common network conditions you usually get +-1ms, going up to an uncertainty of up to +-5ms when there's a big range of latency jitter.
Yes that's true, however "perfect" synchronization is actually not a requirement!
Even +-32ms would still be acceptable
We're building games after all, not synchronizing atomic clocks.
I'm just coming from a practical angle. We also used the Stopwatch timer with this synchronization technique, and it failed, unfortunately. We were forced to regular resynchronize the time.
Using ticks tracking, you can do less work for a better result, lower bandwidth cost, and the implementation is simple.
Channels in progress. I just don't have enough time for now. (and new packet type already in master branch)
I really don't understand the ticks approach.
What I understand : Server communicate ticks, ticks are just a "turn" of the game.
Normally each client have to wait the tick server to do something, and for smoothing things client just execute command on currentServerTick -2.
I don' t understand why clients have to recalculate ticks if the server tell them what is the current tick, but ok maybe.
Normally client have to tell the server that they executed all command for tick -2, so the server can increment the ticks. But in the example I don't see this...
With this technique your game is locked at the worst client (in term of connection or just in term of processing incoming command). Which is good and necessary if your main purpose is to simulated thousand of units in a predictable game and you have no choice. But you can't do that on a FPS game, or MMORPG, or whatever not fully deterministic (hello physics ).
With this process, you can't play your game "locally", you have input lag, and this technique is not what we see in all modern games where clients extrapolate the result and are sometime corrected by server...
Maybe ticks approach is not well explained as TimeStamping technique or maybe I'm just stupid =/
Tick is a unit of time, and it's not restricted to use in a particular networking model. It's only up to you how to use it to synchronize things. There's a lot of information across the web, ECS is the way to go in your case.
Yeah I think to, if you use Ticks like I explained (locked to the slower player) ECS will save you (because you can Tick your game when you want).
Is it that or not ? xD
@nxrighthere I've taken a look at that link.
That is EXACTLY what we are doing! (except with additional management steps to ensure no drifting, and re syncing over time)
I'm not sure why we both thought the other one was talking about something different.
What I don't get though is why it is called tick-based synchronization. This has literally nothing to do with lock-step ticks, you just send timestamps back and forth... Maybe I'm missing something really obvious.
Thats not what i mean. In the features it says "peer to peer connections". Does that mean that the server just lets peers know each other or does it just mean you can make a p2p server?
Let me clear up some of the confusion:
The "server" (whatever that may be, because everyone can be a so called "host"), called 'NetManager' in this library doesn't have any built-in functionality to let other connected peers (aka hosts) know about new connections.
There's no built-in functionality to let peers know about the connections of other peers.
Also, by "p2p server" you mean a sort of bootstrap node, right? (I'm a little confused because in a peer-to-peer network everyone is a server and client at the same time, like in bit-torrent)
If a client writes a message, does that client send the message to all clients, or does it just send it to the server for me to process it? (And yes, a bootstrap node)
I want to make a server authoritative library on top of this. I just want to know if its possible or if this library is really only good for making peer to peer networking.
There's no abstraction layer that'd handle that for you.
You can send a message to a "NetPeer" directly (NetPeer.Send), or to all peers connected to you directly (using a foreach and then using NetPeer.Send), or you could make it so one of the peers acts as a server, then you'd likely create some special message type for that in your own protocol, and your server would detect that and then re-send that message to all other peers.
It's really up to you and depends on what you want to build...
A server authoritative system is what we're doing as well, all game-clients connect to the server, no direct connections between the peers themselves.
Synchronization based on ticks is an alternative to stream-based time synchronization (where you use the Stopwatch timer to synchronize things). You can use the time in this implementation, but dealing with the ticks is easier, and it's more reliable since you know at which tickrate simulation is running on the server/host, and you can make a custom timer based on it. Such timer is hardware independent, and you don't need to send costly long/double across the network. You only need to track ticks and correct them under certain conditions.
Sounds like a pretty good idea. A custom timer that can be kept in sync more easily.
However that also relies on transmitting time. From what I can see in the linked code every packet contains the remote time.
So that's one int (4 bytes) of overhead for every packet.
While I am sending 2 packets (one to the server, one back) every ~20sec, which is 1byte(request ID) + 8bytes (ulong timestamp).
So there is actually bigger network cost involved, no? I'll give the tick based / custom timer solution a try when I have some time. But I wonder if it wouldn't be smarter to send tick updates separately (like I do) instead of having them on literally every message.
Maybe I'm missing something here.