Delivery modes
Each send method sends a packet in one of three ways. You choose the way by the method you call:
| Method | Travels as | Arrives | Use it for |
|---|---|---|---|
SendReliable |
Ordered frames on a QUIC stream | Always, in the order sent | Anything that must arrive: chat, purchases, login, changes to the world |
SendUnreliable |
UDP datagrams | Possibly, and possibly out of order | Frequent updates, where losing one or receiving one late does no harm |
SendUnreliableSequenced |
UDP datagrams, numbered | Possibly, never out of date | Frequent state, such as a position, where only the newest value matters |
The client and the server have the same three methods. See The client for the client's and the server's sends.
Reliable
A reliable packet goes on the connection's QUIC stream. A lost packet is sent again, and packets arrive in the order they were sent. A large reliable packet holds up the reliable packets sent after it on the same connection.
Sending returns before the packet has been written. If the write fails, the error is logged, not thrown.
A serialised packet, with its header, can be at most 32 MB (33,554,432 bytes). A larger one is
refused by the send call itself, which throws InvalidDataException before anything is queued. The
connection stays open. To move a bigger asset, split it into several packets and join them up on
arrival.
Unreliable
An unreliable packet goes as a UDP datagram, outside the QUIC connection. Nothing resends a lost one, and nothing puts them back in order.
A datagram holds just under 64 KB, so keep unreliable packets small. A larger packet is not sent: the error is logged, and the call does not throw.
Unreliable sends need the UDP path to be open. The client has it by the time Connect returns. The
server has it a moment after its Connected event, and until then an unreliable packet is dropped;
see The client. Open the server's UDP ports to clients; see
the firewall section.
Unreliable sequenced
A sequenced packet is an unreliable packet with a number. The receiver keeps the newest number it has passed on, and drops any sequenced packet that arrives after a newer one has been delivered. So a late position update is thrown away, and the next one is the one that counts.
Every sequenced packet on a connection shares one counter, whatever its type. A sequenced packet of one type therefore makes older sequenced packets of any type stale.
Reliable and unreliable packets are not ordered against each other
The reliable stream and the datagrams are separate. A reliable packet and an unreliable one sent in that order may arrive in either order.
Choosing
- Use
SendReliablefor anything that changes the game's state and must not be lost. When in doubt, use it. - Use
SendUnreliableSequencedfor state that is sent often and goes stale: positions, aim, the latest health of an object. - Use
SendUnreliablefor updates that are fine to lose and do not need to be the newest, such as an effect that is only a visual.
Do not send an event that must arrive unreliably, even when the event is frequent. A purchase or a score sent unreliably can be lost, and nothing will ask for it again.