1.2 Tutorials: C#/Unity3d lobby
» Introduction
In this tutorial you'll learn how to build a basic chat and lobby application in Unity3d using the C# bindings for SmartFoxServer.
The example will be able to:
» connect to the server
» log in users
» send and receive chat messages
We'll start by loading the unity project SFSTutorial2 and open up the connection scene by double clicking it in the project view.
» Connection
The connection to the server is made in the Connection scene. Once a successful connection have been established we load the Lobby scene that will do the majority of the work.
The connection scene contains the SmartFox manager and a GameObject called "Connection GUI" with the ConnectionGUI script attached. In the ConnectionGUI script we present the user with two text fields for entering the server IP and port.
The code for the connection scene is very simple, when hitting the connect button this code will tell smartfox to connect to the server. Have a look at ConnectionGUI.cs.
if (GUI.Button(new Rect(100, 140, 80, 24), "Connect"))
{
try {
smartFox.Connect(serverName, serverPort);
}
catch (Exception e) {
errorMessage = e.ToString();
}
}
The actual connection is handled in OnConnection():
if (success)
{
SmartFox.Connection = smartFox;
UnregisterSFSSceneCallbacks();
Application.LoadLevel("lobby");
}
else
{
errorMessage = error;
}
Application.LoadLevel() will simply move us over to the lobby scene.
We should also take care to unregister any callbacks we've registered so the backend doesn't trigger any code in the scene we've just unloaded.
private void UnregisterSFSSceneCallbacks() {
// This should be called when switching scenes, so callbacks from the backend do not trigger code in this scene
SFSEvent.onConnection -= OnConnection;
SFSEvent.onConnectionLost -= OnConnectionLost;
SFSEvent.onDebugMessage -= OnDebugMessage;
}
» Login
After the initial connection is made and we're transported to the lobby scene we start the actual login process. This is a bit more complex, so let's have a closer look at what's happening here.
When the scene loads the first thing we do is to register all the SmartFox callbacks we need, registering a callback is a very simple process.
// Register callbacks SFSEvent.onLogin += OnLogin; SFSEvent.onLogout += OnLogout; SFSEvent.onConnectionLost += OnDisconnect; SFSEvent.onRoomListUpdate += OnRoomList; SFSEvent.onJoinRoom += OnJoinRoom; SFSEvent.onPublicMessage += OnPublicMessage; SFSEvent.onDebugMessage += OnDebugMessage;
The first thing we need to do is to ask the user for a Username, we also let the user decide which zone to log into. In a "real world" setting this is most likely something you don't want to leave up to your users but rather decide for yourself in your code. The zone name corresponds to a zone defined in the servers config file. You can define as many zones as you want and each zone is treated like an isolated world where your users can interact. In this example just leave it at the default of "simpleChat" to connect to a zone that's already defined in the config.xml file, found in the SmartFoxServer/Server folder.

Displaying of this GUI is done in OnGUI() if the variable isLoggedIn is false. Hitting the login button will start the login process:
if (GUI.Button(new Rect(100, 166, 100, 24), "Login"))
{
smartFox.Login(zone, username, password);
}
Calling smartFox.Login will make the OnLogin event fire so in there we just set the isLoggedIn variable to true if the login was successful. Note that if you don't supply any username you will still get logged in as Guest_n (where n is a progressive number). If you don't want players to be able to log in as guests you can turn it off by setting emptyNames to false in the Zone configuration file.
SmartFoxServer/Server/config.xml
<Room name="The Hall" maxUsers="70" isPrivate="false" isTemp="false" isGame="false" autoJoin="true" emptyNames="false"/>
The username can be whatever string, but not all characters are allowed in a username so when the user tries to log in the username is sent to the server, processed and then sent back to the client. The server also does not allow two identical usernames and will also check if your password matches. If the server for one reason or another doesn't approve of the entered username the success parameter in the OnLogin function call will be set to false and the error parameter set to the reason. If this happens we'll display the error message by storing it in the loginErrorMessage variable.
void OnLogin(bool success, string name, string error)
{
Debug.Log("On Login callback got: " + success + " : " + error + " : " + name);
if (success) {
isLoggedIn = true;
} else {
loginErrorMessage = error;
}
}
» Lobby and Chat
After we've successfully connected and logged in we'll display the actual lobby. First of all have a look at the following image that shows how we've layed out the interface;

In the previous section we created an event handler to manage the login response, but there's one more thing we should do to complete this activity. When a login request is successful you will want to recieve another event; The missing one is called onRoomListUpdate. This event will be called with a list of available rooms to join.
This happens because upon reception of a successfull login the client API automatically sends a "getRoomList" request to the server and you need to setup and event handler for it.
Have a look at the OnRoomList method (that we've bound to the onRoomListUpdate event earlier!);
void OnRoomList(Hashtable roomList)
{
List<string> rooms = new List<string>();
foreach (int roomId in roomList.Keys)
{
Room room = (Room)roomList[roomId];
if (room.IsPrivate())
{
continue;
}
Debug.Log("Room id: " + roomId + " has name: " + room.GetName());
rooms.Add (room.GetName());
}
roomListReceived = true;
roomStrings = rooms.ToArray();
// Users always have to be in a room, so lets go to the Hall as our main "lobby"
if (smartFox.GetActiveRoom() == null) {
smartFox.JoinRoom("The Hall");
}
}
There's quite a few things happening here, first we loop through the list of rooms we've recieved in roomList. If a room is flagged as private, we simply skip it for now. Then we populate the two global array roomStrings, and finally we make sure the player is always in a room. If the active room is null we join "The Hall".
The roomStrings array will then later be used to display the room list in OnGUI.
// Room list
if (roomListReceived)
{
GUI.Box(new Rect(490, 80, 180, 170), "Room List");
GUILayout.BeginArea (new Rect(500, 110, 150, 130));
roomSelection = GUILayout.SelectionGrid (roomSelection, roomStrings, 1, "RoomListButton");
if (roomIDs[roomSelection] != currentActiveRoom.GetId())
{
smartFox.JoinRoom(roomStrings[roomSelection]);
}
GUILayout.EndArea();
}
We won't touch too much on this, please read the Unity3d documentation on how GUILayout.SelectionGrid works. To be brief though this basically creates a list of buttons with our array, if the user clicks a button we join the room clicked.
Lets sum up what we've done so far:
1) We've established a socket connection with the server.
2) We've send the server a login request for a specific zone in the server and handled the onLogin and onRoomListUpdate events.
3) We've displayed a listbox of all the rooms that when clicked will send a JoinRoom request to the server, but we've yet to define a response handler for this so that will be our next step.
This is really a very simple function.
void OnJoinRoom(Room room)
{
Debug.Log("Room " + room.GetName() + " joined successfully");
messages.Clear();
}
All we do here is to clear the message window.
» Sending and receiving messages
Now we can examine the heard of a chat application; how to send and receive messages.
We already have our input textbox ready for use and a "Send" button, all defined in OnGUI.
newMessage = GUI.TextField(new Rect(10, 480, 370, 20), newMessage, 50)
if (GUI.Button(new Rect(390, 478, 90, 24), "Send") || (Event.current.type == EventType.keyDown && Event.current.character == '\n'))
{
smartFox.SendPublicMessage(newMessage, currentActiveRoom.GetId());
newMessage = "";
}
When the button is clicked (or we hit the return key in the textbox!) we will call SendPublicMessage with the content of the textbox to our currently active room and clear the textbox so it's ready for a new message.
Now lets see how we handle the reception of a public message. The event to look for is OnPublicMessage;
void OnPublicMessage(string message, User sender, int roomId)
{
messages.Add(sender.GetName() + " said " + message);
chatScrollPosition.y = Mathf.Infinity;
Debug.Log("User " + sender.GetName() + " said: " + message);
}
The event handler recieves a message string (message), and user object (User); We simple add the users name and the message to the messages array (which will be displayed in OnGUI). We also set the scroll position to the maximum to scroll the message area down so the last message is always visible.
Please take your time to go through all these instructions and also check out the source code as it can help you in better understanding the code flow.
| doc index |