Jump to content
  • Advertisement
  • 07/30/14 03:05 AM
    Sign in to follow this  

    Multilevel-Multiplayer with Unity

    Networking and Multiplayer

    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.
    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#.


    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.
    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.


    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

      Report Article
    Sign in to follow this  

    User Feedback

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

    Share this comment

    Link to comment
    Share on other sites

    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?

    Share this comment

    Link to comment
    Share on other sites

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

    Share this comment

    Link to comment
    Share on other sites

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

    Share this comment

    Link to comment
    Share on other sites

    Create an account or sign in to comment

    You need to be a member in order to leave a comment

    Create an account

    Sign up for a new account in our community. It's easy!

    Register a new account

    Sign in

    Already have an account? Sign in here.

    Sign In Now

  • Advertisement

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!