Multilevel-Multiplayer with Unity

Published July 30, 2014 by Sorin Albu, posted by albusorin
Do you see issues with this article? Let us know.
Advertisement
In this article I will describe my experience with Unity by creating a Multiplayer-Multilevel 3D application. I'm not calling this a "game" because I intend this to be something where you don't need to shoot, or destroy, or earn money, or all other game stuff. So what is the application doing: in a 3D environment with streets/buildings you can communicate with other users directly or leave a message at their home. For now it's simple, but in the future I want to enable voice, and home customization, and different types of buildings like: schools/companies/organizations/conference buildings. StreetShot1.png You can try this on: http://www.meeworld.net

Development considerations

Unity is a great tool, you directly work in a 3D scene where you can add objects and manipulate the terrain. For each object you can add different components, that are already existing in Unity, or you can implement those. Unity has also an Asset store where you can find a lot of 3D objects/scripts. The debugging part is also very interesting, when you run the application you can switch to Scene View and make modifications as you want and see results directly in your Game play. I also took into consideration Unity because I'v used .NET for over 6 years, so I'm used to it. Unity also can be used with JavaScript, but for me it was easier to work with C#.

Networking

There are a lot of articles about networking in Unity, I don't want to go deeper into that, but basically there is a MasterServer that handles the communication between applications. One of those applications can be the server that can handle the server operations, and all the clients go through the server and send information through RPC (Remote Procedure Call).

Multilevel-Multiplayer in Unity

The application currently has different streets, where there are different buildings. So a user can go to a street where can meet other users, so for that I had to send the position of the users only to those from that street. Ok, and how to do that? Unity has NetworkView.group, and SetLevelPrefix() but it didn't help me for a multilevel-multiplayer application. This was the hardest part to make, because I didn't find anywhere exactly how to do that with Unity. Of course, you can find some third-party that can be used. networkViewDisable.png Unity has the component NetworkView that synchronizes an observed component. This is working okay if you have a single scene with all the users. But if you have different scenes where the users can enter, the NetworkView with the synchronized observed component is not a good choice, because the NetworkView will send the information to all the scenes. So, the first thing to do was to disable the NetworkView synchronization and send the player state only to other players from the same level. For that the server should know on which level (scene) each player is located. So the call of the client is something like this: On client(send the status to the server): void Update() { if (lastLocalPlayerPosition != localPlayerObject.transform.position || lastLocalPlayerRotation != localPlayerObject.transform.rotation) { networkView.RPC("ServerUpdatePlayerPosition", RPCMode.Server, lastLocalPlayerPosition, lastLocalPlayerRotation, level); } } On server(filter the players and send the update only to the ones from the same level): [RPC] void ServerUpdatePlayerPosition(Vector3 pos, Quaternion rot, string level) { foreach (PlayerProperties player in server_OnlinePlayers.Values) { if (player.Level == level && player.NetworkPlayer != Network.Player) networkView.RPC("ClientUpdatePlayerPosition", player.NetworkPlayer, p, pos, rot); } } On other clients: [RPC] void ClientUpdatePlayerPosition(NetworkPlayer p, Vector3 pos, Quaternion rot) { var thePlayer = FindPlayer(p); if ( thePlayer != null && thePlayer.GameObject != null) { var controller = thePlayer.GameObject.GetComponent(); controller.position = pos; controller.rotation = rot; } }

Some Tricks

How to send custom objects through RPC calls.

Unity does not allow sending on RPC calls according to their documentation; only int/string/float/NetworkPlayer/NetworkViewID/Vector/Quaternation. To send a different type of object you must serialize the object and de-serialize. First I used strings for that but it was a problem with strings larger than 4096 chars, and then I found that that Unity accepts also arrays of bytes, so I used this feature. For example to send an object UserMessage with different properties (Date, UserId, Message, Type,..etc.) through an RPC call, it's impossible because that object is not accepted, so I serialize the object like this: public static byte[] Byte_ConvertObjectToBinary(object obj) { MemoryStream o = new MemoryStream(); BinaryFormatter bf = new BinaryFormatter(); bf.Serialize(o, obj); return o.GetBuffer(); } and send through a rpc call: networkView.RPC("Server_NewMessageAdded", networkPlayer, Utils.Byte_ConvertObjectToBinary(userMessage )); and on the client de-serialize: public static object Byte_ReadFromBinary(byte[] data) { if (data == null || data.Length == 0) return null; var ins = new MemoryStream(data); BinaryFormatter bf = new BinaryFormatter(); return bf.Deserialize(ins); }

How to attach a custom object to a game object

(that is not derived from MonoBehaviour): I added to the game object an empty object that has a TextMesh, so on text property I serialize an object as a string, and when I need the object I de-serialize the object back and use it.

Free 3D objects

For this application I needed some 3D objects, but I'm not a 3D modeler so I needed some objects to place into the application. Sketchup is a great tool, where you create or find a lot of free 3D models. Also on Unity Asset store there are a lot of free objects.

Conclusion

Working with Unity was great, and for me was a new experience to see how 3D game application can be done. Another great thing with Unity is that the application can be compiled for: Windows/Linux/Android/BlackBerry/iOS/Windows Phone 8/unity WebPlayer/XBOX/Wii. If you have questions or do you want to help on continuing this application please don't hesitate to contact me. Thanks for reading, Sorin
Cancel Save
1 Likes 6 Comments

Comments

Irlan Robson

I like small articles. They are very understandable and fits well on the screen. Nice article.

February 26, 2014 06:36 PM
reigota

Good article, as irlanrobson said. Concise, pratical, usefull.

February 27, 2014 11:38 AM
xexuxjy

Good article though serializing objects to byte[] like that isn't going to me very memory friendly I think.

February 27, 2014 05:23 PM
albusorin

Yes byte[] conversion will take some processing, and also some memory, but to send custom objects that are larger than 4096 this is the best way. The other way will be to split the message and send it with multiple [RPC] calls. What do you prefer?

March 18, 2014 12:01 PM
Troy Walker

I guess after the converting to a byte stream, you could run a fast compressor on it too....

July 30, 2014 05:32 AM
mohessaid

very cool, if you continue you will end up with a new version of secondilfe, thanks for the article.

July 30, 2014 10:25 AM
You must log in to join the conversation.
Don't have a GameDev.net account? Sign up!

My experience with Unity by creating a Multilevel-Multiplayer application

Advertisement

Other Tutorials by albusorin

albusorin has not posted any other tutorials. Encourage them to write more!
Advertisement