Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Implementing Multiplayer with MasterServer

Discussion in 'Scripting' started by StickyKeyStudios, Nov 11, 2014.

  1. StickyKeyStudios

    StickyKeyStudios

    Joined:
    Jun 23, 2014
    Posts:
    33
    Hello,

    I want to implement Multiplayer into my game before I begin thoroughly developing the game. I understand there are different ways of doing this, one is using the MasterServer that is hosted by Unity, and others such as Photon that require subscriptions.

    What I want to do is what several other Unity games do, such as Unturned. You supply an IP address, a port, and a password, and you can connect to the specified server (Assuming it's running). How does this work? Is this using the MasterServer but locally (Download the MasterServer and run it, then set the MasterServer.ipAddress to 127.0.0.1 in the code), or something else?

    If anyone knows how Nelson Sexton, the creator of Unturned, did his networking could someone explain?

    Thanks
     
  2. KelsoMRK

    KelsoMRK

    Joined:
    Jul 18, 2010
    Posts:
    5,539
    You can direct connect with IP via LAN or something that emulates it like Hamachi (this is how we test internally). Or you can also just take the user input and set it as the Master Server IP. If there is a Master Server listening on the other end then you'll connect to it.

    Setting the master server IP address to 127.0.0.1 would only work for you though and locally running the master server would require you to forward the necessary ports on your router so outside connections could traverse correctly to your machine.
     
  3. StickyKeyStudios

    StickyKeyStudios

    Joined:
    Jun 23, 2014
    Posts:
    33
    So when the host wants to open a game for everyone, I would set the MasterServer.ipAddress to the host's external IP address, and when a user wants to connect, what do I do?

    How do I make the MasterServer a part of the game, such that if I were to export my Unity game to, Steam for example, the MasterServer would be launched, without creating a new window, and allow the user to then open a server?
     
  4. KelsoMRK

    KelsoMRK

    Joined:
    Jul 18, 2010
    Posts:
    5,539
    That's not how the Master Server works. It basically just manages lists of available games. A player doesn't need to launch the master server locally to host a game - he simply connects to the master server and then registers a game with it. Other players can poll for available games and receive information on how to connect to those hosts.
     
  5. StickyKeyStudios

    StickyKeyStudios

    Joined:
    Jun 23, 2014
    Posts:
    33
    I'm a bit confused then now. Let me simply say what I would like to happen, and then if you could possibly explain how I would go about do so (In Pseudo code?), that'd be extremely wonderful.

    Do I need to use MasterServer at all for this? What kind of code is there that would be needed to do such a task?
     
  6. KelsoMRK

    KelsoMRK

    Joined:
    Jul 18, 2010
    Posts:
    5,539
    That's basically what we do when we test internally. We use Hamachi to turn our remote machines into a virtual LAN which facilitates all the networking stuff. Someone hosts and the others just punch in the host's Hamachi address and everything works.

    What you're describing could theoretically be done with a master server but you'd have to poll for available games and then find the game that matches the IP address the user entered - which is sort of dumb.
     
  7. StickyKeyStudios

    StickyKeyStudios

    Joined:
    Jun 23, 2014
    Posts:
    33
    I don't want to test internally obviously though. How can I instantiate a multiplayer server that others can connect to, without depending on the MasterServer. I'm looking for code, wiki articles, or tutorials that can help.
     
  8. KelsoMRK

    KelsoMRK

    Joined:
    Jul 18, 2010
    Posts:
    5,539
    I don't really understand what you're trying to do. There's no such thing as "instantiating a multiplayer server". If you want people to host games that others can find then you need some software somewhere to manage that. That's what the Master Server or Photon is doing. The player who registered the game is considered the "server" or "host" once everyone is connected (Network.isServer is true for that player only).
     
  9. StickyKeyStudios

    StickyKeyStudios

    Joined:
    Jun 23, 2014
    Posts:
    33
    Okay, I understand that. Now that I know I have to use the MasterServer, how can I use the MasterServer without using the one provided by Unity (Download and install the MasterServer on the hosts machine) and run the local MasterServer when the game is ran, while allowing other players to connect without using Hamachi, just using the MasterServer as a manager as you said.
     
  10. KelsoMRK

    KelsoMRK

    Joined:
    Jul 18, 2010
    Posts:
    5,539
    That's incredibly difficult due to all of the NAT/Firewall/Router things that need to be negotiated. I'd write and deploy my own server code somewhere that managed lookups of hosted games based on IP addresses before I attempted to do that (or use the master server and search the returned HostData for the appropriate IP like I mentioned before).
     
  11. sootie8

    sootie8

    Joined:
    Mar 25, 2014
    Posts:
    233
    https://www.exitgames.com/en/PUN
    I think may prefer using something like this, the first 20 concurrent users are free, so you can use it while developing, for free.
     
  12. KelsoMRK

    KelsoMRK

    Joined:
    Jul 18, 2010
    Posts:
    5,539
    That still requires you to deploy a server somewhere - it's just an alternative to the Master Server but the pattern is the same.
     
  13. FuzzyQuills

    FuzzyQuills

    Joined:
    Jun 8, 2013
    Posts:
    2,871
    I will explain how my implementation works, shall I? :p The should clear things up for most people. First, let's explain how the master server works.

    The way the Master Server works is like this: Basically, all it does is store a table of entries, with each entry holding the game name and type, (this can be something like "KNUCKLE IRON: <nickname>" as this is what my fighting game does. anything will do however, so tweak this however you like) and the IP address and port. This server is usually Unity's master server, but can come from anywhere. (Example in point: I have deployed one before for testing the hosting waters, and it was quite stable. ;)) This data is then made accessible to the compatible game type, that way, several different Unity engine games can run on the same server. And best of all, it handles most of the IP-based stuff for you, of which can be very tedious sometimes... :D

    How my implementation tackles this problem: it is actually quite simple:
    - First, my script pops up a prompt asking if the user wishes to play on a LAN, or Internet. When Internet is selected, the server in the game itself is created. (This is done with Network.InitializeServer) and the code then grabs a URL off the internet (My server URL, in this case) grabs the DNS entry from that, and then my router forwards it to the remote server. (In my case, my crash-test-dummy Dell Mini 9 running Xubuntu Linux and the master server/facilitator)
    - If LAN is selected, it basically initializes the server without any additional setup. It also displays which port and IP was used to do it. That way, when one wants to connect to it, the players share the IP address and port, and enter it into the connection menu.

    And I will also clean up how I set up a master server myself, for those wanting to do this. (For those who use Linux for the server computer, I can PM some pre-compiled builds for you if you like)
    - Firstly, I compiled the master server and facilitator. (Simple step, required you have the right tools installed)
    - Secondly, I started both executables like this:
    Code (csharp):
    1. MasterServer -p <port number>
    2. Facilitator -p <port number>
    I also remeber putting an additional argument in, but I forgot which one that was... :D
    - Thirdly, I then went into my router's firmware settings. What you do is this: first, pick a set of port numbers for the master server and facilitator (I used port 42000/42100) then use port-forwarding to make sure requests to your public IP get routed to the correct destination. Most routers, namely the old speedTouch I used, have an option of selecting which local IP to forward to.
    - Fourthly, I then went online to look for a free DNS host. I eventually picked no-ip.com, as they have a nice free DNS service. In most cases, you simply set it up as an A-type DNS record, and point it to your public IP address. (You get your public IP with whatismyip.com)
    - Finally, make sure everything is connected, then make sure your domain is set up correctly, fire everything up, make sure both the master server and facilitator start correctly, and then test a game with the game code pointed to your DNS hostname (www.example.com, or something similar, I used a servegame.com domain provided by no-ip.com)
    - One more thing: if you try to connect to your server, and something pops up on your server screen about a client connecting, this means your setup is working!

    That is all for now. Good luck! :)
     
    Last edited: Nov 12, 2014
  14. StickyKeyStudios

    StickyKeyStudios

    Joined:
    Jun 23, 2014
    Posts:
    33
    Hello all,

    I was able to reach what I was wanting through some very intensive testing. What the provide code does (Below) is starts a server on your end, using your IP address, the port 25444, and allocates space for 4 players. When someone wants to connect, they have to type in your external IP address (The below example uses 127.0.0.1 as I've been testing this on my machine, and there was no need to get my external IP).

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class NetworkManager : MonoBehaviour {
    5.  
    6.     public GameObject playerPrefab;
    7.  
    8.     // Use this for initialization
    9.     void Start () {
    10.    
    11.     }
    12.  
    13.     void OnGUI()
    14.     {
    15.         if (!Network.isClient && !Network.isServer)
    16.         {
    17.             if (GUI.Button(new Rect(100, 100, 250, 100), "Start Server"))
    18.                 StartServer();
    19.  
    20.             if (GUI.Button(new Rect(100, 250, 250, 100), "Connect"))
    21.                 ConnectToLocal();
    22.         }
    23.     }
    24.  
    25.     void OnServerInitialized()
    26.     {
    27.         SpawnPlayer();
    28.     }
    29.  
    30.     void OnConnectedToServer()
    31.     {
    32.         SpawnPlayer();
    33.     }
    34.  
    35.     void OnPlayerDisconnected(NetworkPlayer player)
    36.     {
    37.         Network.RemoveRPCs(player);
    38.         Network.DestroyPlayerObjects(player);
    39.     }
    40.  
    41.     private void StartServer()
    42.     {
    43.         Network.InitializeServer(4, 25444, !Network.HavePublicAddress());
    44.     }
    45.  
    46.     private void ConnectToLocal()
    47.     {
    48.         Network.Connect("127.0.0.1", 25444);
    49.     }
    50.  
    51.     private void SpawnPlayer()
    52.     {
    53.         Network.Instantiate (playerPrefab, new Vector3 (0, 0.1f, 0), Quaternion.identity, 0);
    54.     }
    55. }
    56.  
    EDIT: Obviously with some basic editing and GUI controls one could turn this into a complete Start Menu that allows the host to change the port, number of players, and even the server password with the Network.incomingPassword value http://docs.unity3d.com/ScriptReference/Network-incomingPassword.html
    The user who wants to connect wold also be able to set these variables.

    EDIT2: If you're using a password Network.Connect() would require 3 arguments, IP address, Port, and the password. If a server uses no password, you could use Network.Connect(int IPAddress, int Port, "")
     
    Last edited: Nov 12, 2014
  15. FuzzyQuills

    FuzzyQuills

    Joined:
    Jun 8, 2013
    Posts:
    2,871
    That is some nice code. (Neater than my rat's nest! :D You can thank GUI code for that)

    Anyway, know GUI scripting of any kind? (Unity's GUI, NGUI or another system will do) If so, make two text fields, one for IP addresses and one for ports. then have the player enter the IP address into one field, and a port number into another. On the server computer, add code that shows the IP address and port to the player, so said player can tell the clients what it is they need to enter.

    Just some ideas I took from my experience writing my own script.

    If you need any further help, feel free to PM me on it. :)
     
  16. sootie8

    sootie8

    Joined:
    Mar 25, 2014
    Posts:
    233
    I think that was directed at me :) . No it does not require you to deploy a server, it is all hosted 'in the cloud' by photon. It deals with match making and NAT stuff amongst other things, and keeps your players synchronised over the network.
     
  17. FuzzyQuills

    FuzzyQuills

    Joined:
    Jun 8, 2013
    Posts:
    2,871
    I think that guy mean't that if you're using Unity default networking. As for photon... it actually does that? :eek:
    That's cool! :)
     
  18. KelsoMRK

    KelsoMRK

    Joined:
    Jul 18, 2010
    Posts:
    5,539
    Um...that's still a server deployed somewhere. Someone else just deployed it for you.

    That's not guaranteed to work in all instances. If there is a router between your machine and the outside world then chances are good that the messages won't make it to you.

    Of course it would work with 127.0.0.1 because you're just connecting with yourself :)