How to use Lidgren with Unity3D for MMOs – Part 1
The debate between TCP and UDP for MMOs is as strong as ever and I’m certainly not going to talk about it here. For Ghostees, I am using UDP and the Lidgren library. It’s open source, free but best of all it solves a lot of the issues revolving around using UDP as your transport.
The types of things you can encounter with UDP can be a pain but since it is low level, you get incredible flexibility and performance.
Think of UDP as a message passing protocol as opposed to TCP which is a stream based protocol. TCP will ensure that your data makes its way across the trenches of the internet in tact and in order. UDP on the other hand makes no guarantees. Some messages may go missing. You might even get two of the same or get messages out of order. Tricky stuff. Lidgren takes care of all that stuff for your but only where you want it. It will definitely let you shoot yourself in the foot also.
The (very) Basic Server
By the way, Lidgren builds in Mono so you can run your server on Linux. I’m pretty sure it works but I haven’t done enough testing to say 100% at this point and I’m pretty much a Windows guy. Enough yapping, lets get coding.
Start a new project for your server and create your server class. I prefer to add the Lidgren project to my solution but either way, add a reference to Lidgren.Network.
Your class will need two private members to start: NetServer and NetBuffer, both in the Lidgren.Network namespace.
class MyServer
{
private NetServer server;
private NetBuffer buffer;
public MyServer()
{
var config = new NetConfiguration("hello-world");
config.Port = 42948;
server = new NetServer(config);
buffer = new NetBuffer();
server.Start();
}
}
Lets go through this quickly. On line 3 the NetServer is the class from Lidgren that will listen for incoming traffic. The NetBuffer on the next line is what we read our messages into. We can reuse it so it is declared as a class member.
We create an instance of NetConfiguration to pass configuration information into the NetServer constructor. NetConfiguration takes a single string argument that is our application identifier. This can be anything you like as long as both the client and server use the same string.
DOH! you wouldn’t believe how many times I’ve had projects where I change the application identifier on either the client or server but not the other and then subsequently spend w-a-a-a-y too long trying to figure out why I can’t connect.
On line 9 I set the port that the server will listen on for incoming messages. Choose pretty much any number you like that is less than 65535 as long as it doesn’t conflict with another application listening on the same port. Only one port per network card can be in use at any time. You are best off choosing a number somewhere over 32768 to avoid “well known” ports.
Lastly, we just call Start() on the server to have it bind to the port and buffering messages.
The Pump
When the server receives a message, after some processing it places it into a queue. This all happens behind the scenes in another thread. You need to write code to retrieve them. I usually have a single thread reading and distributing incoming messages and you might as well make it your main thread. Add this method to your server class:
public void Process()
{
NetMessageType type;
NetConnection source;
while (server.ReadMessage(buffer, out type, out source))
{
HandleMessage(buffer, type, source);
}
}
Your server host, whether its a console application or Windows service, will be responsible for pumping the messages by calling Process. Avoid the temptation of over complicating your server with a thread for the message pump. You won’t see any speed or efficiency increase putting more threads in here.
Each time through the while loop, the server will hand you one message. It will also give you the type of message and which client connection it came from.
The Mail Room
Now we need to decide what’s in the message we just got, and what to do with it. You will receive messages not only from your connected clients but also from Lidgren. Lets cover Lidgren’s messages first.
Among the several types of messages Lidgren can send you, debug messages are one of the two basic ones you definitely want to handle. They will simply be strings that you can output to the console or debug stream.
Another message you want to handle is the StatusChanged message. This message tells you when someone has connected or disconnected. I’ve created another method called HandleMessage which is where I will switch on the message type.
The last of the most basic messages is the Data message. These are messages sent to you from your connected clients.
I would suggest you throw an exception or at least log a warning if a message comes through that you didn’t handle. I’ve caught many weird bugs this way simply because I wasn’t aware I was receiving a BadMessageReceived or other message.
public event Action<NetConnection> ConnectionStatus;
public event Action<NetConnection, NetBuffer> DataReceived;
private void HandleMessage(NetBuffer buffer, NetMessageType type, NetConnection source)
{
switch (type)
{
case NetMessageType.DebugMessage:
{
Debug.WriteLine(buffer.ReadString());
break;
}
case NetMessageType.StatusChanged:
{
if (ConnectionStatus != null)
ConnectionStatus(source);
break;
}
case NetMessageType.Data:
{
if (DataReceived != null)
DataReceived(source, buffer);
break;
}
default:
throw new NotImplementedException("Message type not handled: " + type.ToString());
}
}
You can see in the snippet above on the first two lines, I’ve declared two public events. Other classes in your server will want to know when a client comes and goes so its wise to publish this information. The other event gets fired when we receive data from clients.
HandleMessage works its magic by simply switching on the message type. In the case of a debug message, we simply write it to the debug stream. In the case of a ConnectionStatus or Data message, we fire the appropriate events.
OK so here is the code so far:
using System;
using System.Diagnostics;
using Lidgren.Network;
namespace BakedOn
{
class MyServer
{
private NetServer server;
private NetBuffer buffer;
public event Action<NetConnection> ConnectionStatus;
public event Action<NetConnection, NetBuffer> DataReceived;
public MyServer()
{
var config = new NetConfiguration("hello-world");
config.Port = 42948;
server = new NetServer(config);
buffer = server.CreateBuffer();
}
public void Process()
{
NetMessageType type;
NetConnection source;
while (server.ReadMessage(buffer, out type, out source))
{
HandleMessage(buffer, type, source);
}
}
private void HandleMessage(NetBuffer buffer, NetMessageType type, NetConnection source)
{
switch (type)
{
case NetMessageType.DebugMessage:
{
Debug.WriteLine(buffer.ReadString());
break;
}
case NetMessageType.StatusChanged:
{
if (ConnectionStatus != null)
ConnectionStatus(source);
break;
}
case NetMessageType.Data:
{
if (DataReceived != null)
DataReceived(source, buffer);
break;
}
default:
throw new NotImplementedException("Message type not handled: " + type.ToString());
}
}
}
}
In the next part, I will show you how to create a client that will work within Unity. It’s not tough at all. And if you deep-tech readers are concerned what we have done here is far too simplistic, not to worry. We will be going much deeper. After the client, we will start talking about message formats, serialization and message envelopes.
If this topic is useful or interesting to you, shoot me a quick comment and let me know so I’ll keep going with it.
6 Comments › Leave yours
1 Trackbacks
- Tweets that mention BakedOn Entertainment – Online Multiplayer Games » How to use Lidgren with Unity3D for MMOs – Part 1 -- Topsy.com - [...] This post was mentioned on Twitter by BakedOn Entertainmen. BakedOn Entertainmen said: Thinking about writing a series on how ...
Leave a Reply
Search this Site
- RT @FGSummit: Here's your chance to win a FREE ticket to #FGS2012!!! Retweet for a chance to win!
- I just contacted Rep. Jay Inslee to oppose #SOPA/#PIPA - Join me! http://t.co/5x8XAhYY #wikipediablackout
- Tell Congress: Don’t censor the web! http://t.co/IzEmL336
- I just backed Guns of Icarus Online on @Kickstarter http://t.co/C1ImM8e7 The original game was great and this looks fantastic. @MuseGames
Archives
- April 2010 (1)
- March 2010 (1)
- February 2010 (1)
- January 2010 (2)
- September 2009 (1)
- December 2008 (1)
- July 2008 (2)
- March 2008 (1)
- February 2008 (1)
- November 2007 (1)
- October 2007 (1)

Nice, any chance to see part to.. Also what sort of server back end are you using for Unity.. is this a basic LAMP setup, with sending data packets via lidgren. We are looking at what is the best solution for social game using unity but a bit worried about the communication layer, security and load. any pointers?
i am very interested in web-game mmo developemt, looking forward part II
Thanks for this. I have been away from game programming for a lot of years and trying to remember things I once did on a daily basis is frustrating hehe.
This is really, really helpfull! Exactly what I’ve been looking for and it helps very much! I really hope you continue with the rest!
Excelent! keep up good work.
Will we be seeing part two soon?