Table of Contents

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 SendReliable for anything that changes the game's state and must not be lost. When in doubt, use it.
  • Use SendUnreliableSequenced for state that is sent often and goes stale: positions, aim, the latest health of an object.
  • Use SendUnreliable for 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.