Search Unity

This blog is the third in a series about our upcoming networking technology known internally as UNET. We want UNET to be a system that all game developers can use to build multiplayer games for any type of game with any number of players as easily as possible. We’ll be launching UNET in the 5.x cycle.

Get a general overview of the UNET system here, or read on to learn about the UNET transport layer foundation!

When we started to design the new network library for Unity, we want to understand what an ideal library would look like. We realized that we have (roughly) two different types of users:

1.   Users who want networking tools that will give them an out of the box result with minimal effort (ideally without any effort at all).

2.   Users who develop network-centric games and want very flexible and powerful tools.

Based on these two user types, we divided our network library into two different parts: a HLAPI (high-level API) and a LLAPI (low-level API).

If you’re interested in learning more about the Syncvars we use in the high level API you can read more here. The following discussion relates to the low level API and our library design which was based on the following principles:

Performance, performance, performance…

The LLAPI is a thin layer on top of the UDP socket, most of the work is performed in a separate thread (hence LLAPI can be configured to use the main thread only). There’s no dynamic memory allocation and no heavy synchronization (actually most of the library uses memory barrier synchronization with some atomic increment/decrement operation).

If something can be done using C# it should be

We decided to only expose what we felt our users would need to use. Like BSD sockets, the LLAPI supports just one abstraction – exchanging raw binary messages. There are no tpc-like streams, serializers or RPC calls in the LLAPI; only low level messages.

Flexibility and configurability? Yes please…

If you take a look at TCP socket implementation you can find tons of parameters (timeouts, buffer length etc.) which you can change. We chose to to take a similar approach and to allow users to change almost all of our library parameters so they can tune it to their specific needs. Where we faced a choice between simplicity and flexibility we sacrificed simplicity to flexibility.

Nice and easy

We tried to design the LLAPI to resemble the BSD socket API wherever possible.

Network and transport layers

Logically, the UNET low level library is a network protocol stack built on top of the UDP, containing a “network” layer and a “transport” layer. The network layer is used for creating connections between peers, delivering packets and controlling possible flow and congestion. The transport layer works with “messages” belonging to different communication channels:

communication channels

Channels serve two different purposes, they can separate messages logically and they provide different delivery grants or quality of service.

Channels configuration is a part of configuration procedure, something we’ll discuss in more detail in an upcoming post. For now, lets just consider the configuration part as “My system will contain up to 10 connections, each connection will have 5 channels, where channel 0 will have this type, and channel 1 will have other type and so on”. The last part of this sentence is defined by:

The second parameter is channel number and last is channel type, or channel qos (delivery grant).

UNET (so far) supports the following QOS:

  • Unreliable: An unreliable message which can be dropped due to network conditions, or internal buffers overflow, similar to UDP packet.  Example: Short Log Messages
  • UnreliableFragmented: Maximum packet length is fixed, but sometimes you will probably want to send “big” messages. This channel type will disassemble your message to fragments before sending, and assemble it back before receiving. As this qos is unreliable, delivery is not granted.  Example: Long  Logs
  • UnreliableSequenced: Channel grants delivery order, as this qos is unreliable, the message can be missed. Example: voice, video
  • Reliable: Channel grants delivery (or disconnect) but not grant order.  Example: Sending Damage
  • ReliableFragmented: Same as UnreliableFragmented, but additionally it will grant delivery.  Example: Group Damage
  • ReliableSequenced: Same as UnreliableSequenced, but additionally it will grant delivery. This QOS is analogous to TCP stream.  Example: File Delivery/Patching
  • StateUpdate: An unreliable channel type plus channel with this qos will force drop messages which are older than sending/receiving. If when sent, send buffer contains more than one message, only the youngest will send. If the receiving buffer, when reading, contains more than one message only the youngest will be delivered.  Example: Sending Position
  • AllCostDelivery: Fairly similar to Reliable qos, but there is a difference. The reliable channel will resend undelivered messages based on round trip time value (RTT) which is a dynamic parameter while AllCostDelivery will automatically resend messages after a period of time (configured value). This can be useful for small important messages: “I shot player A in the head” or “Mini-game starts”.  Example: Game events such as firing bullets

If you have a use case you feel doesn’t fit conveniently in these categories, we’d love it if you could bring it up in the comments!

Let’s review typical LLAPI function calls:

1.       Initialize library

2.       Configure network: topology, channels amount, their types, different timeouts and buffer sizes (we discuss this in a later post)

3.       Create socket:

This function will open the socket on port 5000 on all network interfaces, and will return an integer value as a descriptor of this socket

4.       Make connection to other peer:

This function will send a connection request to “other peer” at address It will return an integer value as a descriptor of this connection for this host. You will receive the connection event when the connection is established or the disconnect event if the connection cannot be established

5.       Send message:

This last function will send binary data contained in the buffer via socket described by hostId for peer-described connectionId using channel #1 (in our case this is “reliable channel”, so for this message delivery will be granted.

6.       Receiving network events:

For receiving network events, we chose a poll model. User should poll UTransport.Receive() function to be acknowledged about network events. Note that this model is very similar to ordinary select() call with zero timeout. This function receives 4 different events:

  • UNETEventType.kConnectEvent – somebody connects to you, or connection requested by  UTransport.Connect() call has been successfully established
  • UNETEventType.kDisconnectEvent – somebody disconnects with you, or connection requested by UTransport.Connect() call cannot be established for some reason (error code will report what this reason was)
  • UNETEventType.kDatatEvent  – New data has been received
  • UNETEventType.kNothing – Nothing interesting happened

7.       Send disconnect request:

This function call will send a disconnect request to a connection defined by connectionId on host defined by hostId. The connection will close immediately and can be re-used in the future.

That’s it for now! Thanks for reading, and don’t forget to check back (or subscribe to our blog) to catch the next post in the UNET series in which we’ll be discussing network topology configuration.

54 replies on “All about the Unity networking transport layer”

Hi. Like where this is going. +1 vote for LLAPI + HLAPI working in pair. I could really go wild using LLAPI to lay out network topology and then let HLAPI care about serialization and sending stuff :)
Also, want p2p blog post sooner :)

Great news, I am wondering if server can handle huge number of concurrent client in case of making instant messaging server, something like 100k clients or even more

@AFPRO right now – no, hence i will take a look what we can do :)
@TUTI – I guess that is a topic of other blog, transport layer itself supports p2p

i want to use UNET features like ‘SyncVar’, but i want connect players with bluetooth, is that possible?

@AFPRO sorry I do not understand your question. Sure You can write your own network layer using tcp or bluetooth or custom hardware protocols as (and if) those protocols are supported by OS.

it mentioned that all unet is built on top of udp. i hope i could write my own network transfer layer (eg tcp, bluetooth or my custom hardware like i2c)

> Is that a blocking send?
No, price is 1 memcpy + couple of if()
>How do you handle socket notifications? Would block, send buffer full, etc?
So far there are 3 different models to choose:

1 threaded model where user need call NetworkUpdate from main thread (this model suitable for one core devices and good for debug),

fix rate model, where network thread periodically awakes and does its send/receive job, good for mobile devices

select model, where network thread sleep on select and awakes to do read job, or awakes by timeout to do send job. changing in timeout frequency does flow control to prevent receiver to be overfull with sending messages. Good for pc and consoles

io completion port in the situation when you have only one io thread and only couple of udp sockets doesn’t get a lot of performance (select with one socket 10% worse than iocp with one thread) with select ~150,000 datagrams per second which (i guess) more than enough for client; big plus is that select supported on all platforms…

Server library is totally different task, hence design would be tricky, if we will support iocp with thread pool on single udp socket, some sort of synchronization should be taken into account (and user will need take care about this).

>Would block, send buffer full, etc
if you cannot send message, you will receive false after call Send function and will need to resend message later or drop it.

Is that a blocking send? Based on there not being a completion callback, I’m assuming it is. Ideally the LLAPI would support io completion ports on platforms that can support them. I’m using lidgren right now and it is fairly complete for my usage (and covers the same things as LLAPI from the sound of it), but it also includes message pooling/reuse. Unfortunately it still doesn’t support async I/O with completion ports. I’ve considered rewriting it with that support but its quite a task.
How do you handle socket notifications? Would block, send buffer full, etc?

I’m extremely inspired together with your writing skills as
well as with the layout for your weblog. Is that this a paid topic or did you customize it yourself?

Anyway stay up the excellent high quality writing, it is rare to see
a great weblog like this one today..

Well, I was thinking more in the line of UDP socket broadcasting. It is mighty useful for WLAN multiplayer peer to peer discovery

@GREGORIUS We should define first what is broadcasting is? If you mean send the same message to different users, yes it is supported. If you mean classical socket broadcasting, It is not supported (is it important?). Or may be you mean something else? Could you clarify your question?

@Nicholas We know :) and will try to publish. I cannot promise that we will publish this dll on start, but this task in my to-do list has high priority.

Hence, I do not understand you thing about web application, what do you mean? Ability talk with web service using udp? (UNET has udp nature) I meant standalone dll which will provide the same API but can work without Unity…

One thing that will really be nice is a .net DLL. You know so we can host our own master server on a dedicated windows service or (preferably) a .net MVC web application.

[…] All about the Unity networking transport layer – Unity Technologies Blog. […]


FWIW, it’s possible to use PostProcessSceneAttribute to inject custom objects into your scene(s) at “play” in the editor and when a build is made. These objects could hold components that run your init code automatically, without having to clutter up your scenes at edit-time, and also eliminating the risk of forgetting to set it up in scenes.

@DANIEL so far no, but it looks like “nice to have” feature.
@VICTORIA I do not have any idea when UNET will be accessible for public, right now it is mostly discussion to be sure that we are going in the right direction. We will publish UNET with full API documentation:)
@MIKE good question, it is still under discussion, (other option is webrtc) probably not for a initial release

The new UNET technology seems to give a lot of new possibilities for game developers, but I wonder if there’ll be more documetation on it

@stephan as far as i know, it is history now. Mobile providers blocked it to prevent voip using. With skype on each phone it doesn’t make sense anymore… Let me know please if you have fresh info about udp blocking. Symmetrical nat is a different story, but we are using relay for this

I once tried UDP on mobile devices and had to realize that a lot of the cell phone providers block using UDP. How do you plan to overcome this.

Don’t mind my ignorance here, but is it feasible (for a programmer but new to networking and multiplayer) to use both hlapi and llapi? Perhaps have syncvars for certain variables and objects, but for some events to use a separate channel to send unreliable data or some combination of the above?

@skyblade ipv6 support scheduled so far as nice to have. I will try to support them but cannot promise

@hannibalov i agree with madman, hence event based model makes sense for server (like lobby) as server is driven by network events only.

The HLAPI is (mostly) C#, so it runs in the Unity main thread. Since it uses the polling mechanism of the LLAPI, all user script code that responds to network events will be run in the Unity main thread, so you don’t have to worry about threading issues there.

The HLAPI main loop would look something like:
– poll LLAPI for events
– generate corresponding HLAPI event
– run the registered event handler

Like ALEXEY said you are going to be in the game loop anyway. Also you are going to be doing more than just polling. You should write scripts that handles all this stuff, connection facilitation etc.

“synced with Unity’s main thread so it would be thread safe.”

It’s a little unclear what you are getting at. If you want events it’s trivial to hide the implementation. ALEXEY said that the LLAPI will not be thread safe. I don’t think that many people will be spawning their own threads for networking. Since even at the Low Level API level you will be interacting closely with gameObjects. Thus thread safe events are not needed in my opinion, unless the whole design of unity changes.

The harder part of game networking is actually the client side prediction, dead reckoning, rewinding time, high fire rate weapons prediction etc. Which you will need to handle yourself getting that part done took me months and will be different for each game.


I understand Alexey’s point, but is there any chance we could subscribe to an event when new data arrives? I do it quite frequently with pure c# sockets. And ideally the callback would receive a filled object with the data, the sender, the code, the channel and maybe other stuff, so the callback receiver could filter.

I hope you can still do that because it’s really useful. And it would be even better if it was synced with Unity’s main thread so it would be thread safe.

Perhaps also needed is a ‘ReliableStateUpdate’ mode, whereby it operates like StateUpdate, but with resends, and any resent messages will use the latest state rather than the one that was lost.

Also, I think you mean guarantee/guarenteed instead of grant/granted throughout :)


Why was polling choosing as the method of getting data? was it because you are trying to make it resemble the socket API ?

Will the HLAPI provide event based (callback) API ? btw – is there going to be a following post on the HLAPI?

Really Good And helpful post. i really don’t know about unity networking and transport layer and how its work. i’m learning unity from last 8 months so i daily read all article to learn more.
Thank you :D

How come we have to call UTransport.Init() ourselves? Can’t you do this as part of engine startup?

If we have to call it ourselves, what’s the best place to do that? Note that it’s a bit of a pain having this kind of ‘subsystem’ init attached to GameObjects as it means having to either put the object in each level that we might enter playmode with, or do shenanigans with singletons or something (and similar problem with e.g. third-party audio plugins like WWise). It’d be nice if there was some way to write code that always ran when entering/exiting playmode, without having to put stuff into the scene…

From what I have seen so far I like the architecture of the LLAPI. 255 channels meets my needs.

This sound good, seems like UNET could meet my needs after all.

1: Right now I use a single Unreliable channel and timestamp/ id each message for my RTS type game, I am limited to 32 Sequenced channels which would not be enough to allocate a channel for each unit’s position. I look forward to the post about how many channels you can have. I am guessing that the number is quite limited? I assume the channels are per connection?

2: If you use uint16, keeping it a uint16 is clearer I don’t mind casting. I like to know what data types I am working with.

3: The way I read the description of StateUpdate is that it’s not guaranteed to be sequential. Am I reading that right? Or are you saying that it does not try to resequence the messages in buffer?

4: It sounds like you will support multiple topology peer to peer? Even for authoritative servers moving below the level of client/server to sender/receiver seems like a good idea.

5: You are using a BinaryFormatter have you thought of using a Protocol Buffer? protobuf-net v2 seems stable.

Good to see low level access also being made available through unity.
Wondering if there is any further documentation of the api available, or do we really need to wait for unity 5?

Looks very interesting and I’m absolutely looking forward to it :)

and promissing what you have in the pipe there. Reminds on concept level of what I’ve seen in some of my favorite neworking technologies in the past (Torque and NetDog, a pretty cool C based threaded multiplayer library that sadly got killed by surreal pricings)

Hope to get my hands on it more sooner than later as I’ve a project that would be far less of a pain with UNet ;)

What about games with short messages ( like http ):
– connect
– send request
– receive response
– disconnect

Will Unet provide efficient api for such behavior?
Can we use TCP with Unet if we need for some reason?

@Alexey – is there or will there be an early access program? I was already bugging some dude on linkedin to get access but he never replied :)

Or even:

yeah change to:

Naming is very important (at least to me).

Enums whose values start with kXXXX are not very .NET-ish and seem weird.
Building a new library from scratch, i like having everything as perfect as possible (no legacy crap from the past forcing me to do anything). I would change those names if it were possible :)

Connection descriptor is an int? Why limit yourself to only 2,147,483,647 connections?

… just kidding

Looks great :)

How can I communicate between UnityClient and pure .Net Lobby, LoadBalancer or RoomServer using UNET?

In most cases Unity on both sides occurs in communicate of Client and battle server in ither cases server is pure .Net

Comments are closed.