Search Unity

  1. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice
  2. Unity is excited to announce that we will be collaborating with TheXPlace for a summer game jam from June 13 - June 19. Learn more.
    Dismiss Notice

New to Unity - Need help with networking

Discussion in 'Multiplayer' started by whitejasond, Feb 19, 2008.

  1. whitejasond

    whitejasond

    Joined:
    Feb 15, 2008
    Posts:
    4
    I'm fairly new to Unity and I have been getting my hands dirty trying to learn how to do some 'basic' networking. I've been trying to get a simple server / multiple client setup working using RPC and I seem to be missing something.

    What I would like to do is have a simple dedicated server running - using the RAKNET library (which I know Unity uses) and then have a number of Unity clients connect to this and use RPC to send messages to the server and for the server to send back responses.

    I don't need any master server functionality as there will only be one server that all clients connect to.

    Can someone point me in the right direction either via documentation or examples?

    Thanks in advance...
     
  2. jashan

    jashan

    Joined:
    Mar 9, 2007
    Posts:
    3,307
    Personally, I'd set up the server with Unity, as I would guess that in most cases, you'll have rather significant game logic residing on the server, and the way Unity is handling networking (making extensive Use of NetworkViews) might be tricky to set up only using RAKNET (I don't know that API as "standalone", so I don't know how much of what Unity is using is part of that API).

    I could think of a few other good reasons creating your server with Unity, like very nice testing features, sharing code between client and server etc. etc. etc.

    The major disadvantage of that approach is that Unity doesn't support a headless mode, yet - at least not for Unix or Windows (which I think is a much more convenient server OS than Mac OS... simply because it's available, and comparatively cheap to get dedicated servers with these OSs). I hope that when more people are developing multplayer games, the issues involved in setting up (distributed, hosted) standalone servers will be handled... This has been brought up before, so I won't repeat it...

    The solution is to simply switch off the cameras and live with the inconveniences of having an application where you would actually want to have a service (speaking "Windows speak"). Or having to rent a Windows server, where you might prefer renting a Linux box ;-)

    If you can live with that, check out the examples and the documentation - it's really rather well-documented (except for a few things that haven't been updated, yet - you can now use bool and byte[] as parameters for RPCs). The server would then simply be a "different build" of your game project, and based on, for instance, a variable globally accessible through a singleton pattern, you could check the relevant code paths.

    Btw, I'm using the master server functionality even though I'm also only having one single standalone server that clients connect to. Reason is simple: It seemed to me that this is the easiest and most painless way of setting things up (including NAT punchthrough and stuff like that).

    Um... links... see my other posting in thread;

    http://forum.unity3d.com/viewtopic.php?t=9478 (almost at the end, I had a little collection of nice links into the documentation)

    If you really want to build your server based on RAKNET (without Unity wrapping around it), I guess Larus is the only one who can help you ;-)

    Jashan
     
  3. whitejasond

    whitejasond

    Joined:
    Feb 15, 2008
    Posts:
    4
    Thanks Jashan for the information you provided. Perhaps I should explain in a little more detail what I am trying to achieve.

    I have been working on a MUD Server, which is written in C++ and works well, but is currently limited to telnet access. This tends not to give way to a good user interface and does look kind of dated.

    I would like to use Unity as a 'front end' to the server to provide a better, more graphical front end to the server. At first I would just like to have a simple interface, which would simulate what I have already. I would then like to take this further by adding buttons for directions, inventory etc.

    I feel this would be a better approach to learning the ins and outs of an MMO, rather than jumping in the deep end as I have seen so many attempt and fail.

    Which I guess would mean that I fall into the option of adding RAKNET to my existing server to allow me to integrate with Unity.

    I still have not managed to get a stand alone server talking to Unity using RPC, so if anyone else has any information it would be greatly received.
     
  4. jashan

    jashan

    Joined:
    Mar 9, 2007
    Posts:
    3,307
    Hi... um... Jason, maybe? ;-)

    thanks for the clarification... well, from that perspective, it obviously would make a lot of sense to add RAKNET to your MUD-server to get it to talk to Unity. I'm not sure though, how this can be done... Guess it depends largely on the documentation of the "internals" of how Unity networking is implemented on top of RAKNET... I guess Larus might probably tune in to this thread - he's the guy (or at least: one of the guys ;-) ) who's been creating the networking part of Unity.

    If you don't want to wait for that, you might also try sniffing the packets from some RAKNET demo (that you might have to create for this) and sniffing the packets from one of the Unity networking demos - maybe you can decode the protocol(s) involved and create your RAKNET layer that way. You might also want to check out the Master server. As far as I know, it's sources are open - and you can probably gain a lot of valuable insights from there, relevant also to what you're trying to do...

    For the MMO-stuff, having some low-level experience sure wouldn't hurt, anyways ;-)

    Sunny regards,
    Jashan
     
  5. larus

    larus

    Unity Technologies

    Joined:
    Oct 12, 2007
    Posts:
    280
    The message protocol is not documented. Making a separate server using RakNet will be non-trivial to do at the moment, its not directly supported. You could just do your server part in Unity, like Jashan has suggested, maybe in a minimalist way. Then of course you can only run it on Mac and Windows, not Linux.

    If you already have a working server running you could implement the client part using .NET sockets within Unity.
     
  6. whitejasond

    whitejasond

    Joined:
    Feb 15, 2008
    Posts:
    4
    I've found the example below which I think could be made to do what I want. Obviously, I would have to make some changes on my MUD server side to work with this but I think it is certainly possible.

    http://www.unifycommunity.com/wiki/index.php?title=Simple_TCP/IP_Client_-_Server

    Now my question is, how do I get this into Unity and do I need the Pro version to get this working? What I want to do is simply hook it up to the GUI and at first will just have 2 text boxes, 1 for input (a single 80 character line will do for this) and a larger one for the out put from the server, again 80 characters wide but maybe around 20 lines (with side scrolling to go back up).

    I have managed to get it so that if I press a key it sends text to the server. For a simple test I set up the u and p key to simply send the username and password of a character on the MUD, but the integration with the GUI is causing me some frustration at the moment.

    Any help would be appreciated! If I need to buy Pro I don't mind, if that is the only way forward, but I thought I would ask before I get my wallet out.
     
  7. whitejasond

    whitejasond

    Joined:
    Feb 15, 2008
    Posts:
    4
    After a little more playing around I have come up with the following:

    Code (csharp):
    1.  
    2. using System;
    3. using System.Collections;
    4. using System.Runtime.InteropServices;
    5. using System.Security.Permissions;
    6. using System.IO;
    7. using System.Net.Sockets;
    8. using System.Text;
    9. using UnityEngine;
    10. using SharpConnect;
    11.  
    12. public class LinkSyncSCR : MonoBehaviour {
    13.     public Connector test=new Connector();
    14.     string lastMessage;
    15.     string myText;
    16.  
    17.     public Transform PlayerCoord;
    18.    
    19.     void Start ()
    20.     {
    21.         myText = "";
    22.        
    23.         Debug.Log(test.fnConnectResult("192.168.200.121",8888));
    24.        
    25.         if (test.res !="")
    26.         {
    27.             Debug.Log(test.res);
    28.         }
    29.        
    30.     }
    31.    
    32.     void Update ()
    33.     {
    34.     }
    35.    
    36.     void OnGUI ()
    37.     {
    38.         GUI.Label (new Rect(5,5,450,250), test.strMessage);
    39.        
    40.         myText = GUI.TextField (new Rect(5, 250, 200, 20), myText);
    41.        
    42.         if (GUI.Button(new Rect(210, 250, 45, 20), "Send"))
    43.         {
    44.             test.fnPacketTest(myText);
    45.             myText = "";
    46.         }
    47.     }
    48.    
    49.     void OnApplicationQuit ()
    50.     {
    51.         try
    52.         {
    53.             test.fnDisconnect();
    54.         }
    55.         catch
    56.         {
    57.         }
    58.     }
    59. }
    60.  
    61.  
    62. namespace SharpConnect
    63. {
    64.     public class Connector
    65.     {
    66.         const int READ_BUFFER_SIZE = 1024;
    67.         const int PORT_NUM = 10000;
    68.         private TcpClient client;
    69.         private byte[] readBuffer = new byte[READ_BUFFER_SIZE];
    70.         public ArrayList lstUsers=new ArrayList();
    71.         public string strMessage=string.Empty;
    72.         public string res=String.Empty;
    73.  
    74.         public Connector(){}
    75.  
    76.         public string fnConnectResult(string sNetIP, int iPORT_NUM)
    77.         {
    78.             try
    79.             {
    80.                 // The TcpClient is a subclass of Socket, providing higher level
    81.                 // functionality like streaming.
    82.                 client = new TcpClient(sNetIP, iPORT_NUM);
    83.                 // Start an asynchronous read invoking DoRead to avoid lagging the user
    84.                 // interface.
    85.                 client.GetStream().BeginRead(readBuffer, 0, READ_BUFFER_SIZE, new AsyncCallback(DoRead), null);
    86.                 // Make sure the window is showing before popping up connection dialog.
    87.                
    88.                 return "Connection Succeeded";
    89.             }
    90.             catch(Exception ex)
    91.             {
    92.                 return "Server is not active.  Please start server and try again." + ex;
    93.             }
    94.         }
    95.  
    96.         public void fnPacketTest(string sInfo)
    97.         {
    98.             SendData(sInfo);
    99.         }
    100.  
    101.         public void fnDisconnect()
    102.         {
    103.             SendData("quit");
    104.         }
    105.  
    106.         private void DoRead(IAsyncResult ar)
    107.         {
    108.             int BytesRead;
    109.             try
    110.             {
    111.                 // Finish asynchronous read into readBuffer and return number of bytes read.
    112.                 BytesRead = client.GetStream().EndRead(ar);
    113.                
    114.                 if (BytesRead < 1)
    115.                 {
    116.                     // if no bytes were read server has close.  
    117.                     res="Disconnected";
    118.                     return;
    119.                 }
    120.  
    121.                 // Convert the byte array the message was saved into, minus two for the
    122.                 // Chr(13) and Chr(10)
    123.                 strMessage = Encoding.ASCII.GetString(readBuffer, 0, BytesRead - 2);
    124.  
    125.                 // Start a new asynchronous read into readBuffer.
    126.                 client.GetStream().BeginRead(readBuffer, 0, READ_BUFFER_SIZE, new AsyncCallback(DoRead), null);
    127.  
    128.             }
    129.             catch
    130.             {
    131.                 res="Disconnected";
    132.             }
    133.         }
    134.  
    135.         // Use a StreamWriter to send a message to server.
    136.         private void SendData(string data)
    137.         {
    138.             StreamWriter writer = new StreamWriter(client.GetStream());
    139.             writer.Write(data + (char) 13);
    140.             writer.Flush();
    141.         }
    142.     }
    143. }
    144.  
    145.  
    This is very very crude, but it does kind of work! Probably not the best way of doing this, but at least it is a start.

    Comments welcome..