Saturday 22 March 2014

Networking with Photon for Unity

I have not had as much time to spare for this project over the last month as I would have liked.  My real work that pays the bills has been so busy I have only been able to tinker here and there but I am still making good progress. Tinkering in Unity produces results much quicker than it did in XNA.

My decision to develop the menus first to learn how to use Unity has been a good choice. I have learnt a lot about the component model used by Unity and some of the best ways to do things.



I have a menu system that works with the keyboard, mouse and gamepads and I have got as far as adding split screen including a test scene to show it in action.  I have added the usual console style features, like popping up a message when  a gampad disconnects and buttons to show which keys to press.

I am itching to get on and build the levels and add characters to the game BUT from my experiences with XNA I want to sort out how network play will work before I start on the game scenes.  I will eventually get to the main subject of this article which is about using the Photon Unity Networking service.  First a bit about why I chose to use that.

With XNA I made the mistake of developing movement that was difficult to translate in to something that works over a network.

To avoid that I have been reading up on Unity networking.  To cut a long story short the Unity network model is limiting.  Not bad, it just has limits, which is exactly what I needed to know before going too far in the wrong direction.

I won't go in to detail about how Unity networking is used because that was not the point of writing this article.

All that I need to say is that having read lots of forums and tutorials most people have concluded that using a third party network provider has advantages over the built in Unity networking.  Most commonly in threads people quote that Unity have not put much effort in to improving their networking for several years.  The other area mentioned is that the Network Address Translation (NAT) punch through that end users can often have to struggle with on their home routers can be avoided with a cloud provider.

I have therefore decided to use a third party network solution by Exit Games called Photon.

There are several providers to select from but I liked Photon because it has a similar object model to the built in solution which helps when reading samples and tutorials and is also relatively easy to convert from one to the other.  They have also put a lot of effort in to producing Unity samples.

Another important consideration, for me, is that during development it is low cost.  In fact free for 10 concurrent users, which is plenty for testing.

Photon have good documentation and is easy to sign up to at no cost.

https://www.exitgames.com/

I should point out that I have no connection with Exit Games or the Photon service.

Adding Photon networking in to the game is as easy as importing the package.  Making the game work as a network game still requires the same processes of adding network views to moving objects or using Remote Procedure Call (RPC) methods but Exit games have several examples and tutorials.

I was up and running in no time and the add-in includes a Unity Editor menu for putting in the necessary details in to the demo project:


You just need your own AppID from the Photon web site:



Watch out for their web site though.  It has a drop down to swap between the various services they provide.  Look out for Photon Unity Networking (PUN).



You get different menus, different documentation and different account details if you have selected a different service.

Testing

Unity will only run one instance of the same project so I made two copies of the Photon Demo project, set one to run in the background...




...left the other unchanged.  Opened both in Unity and ran them both side by side:





Photon has another advantage in that single player and multiplayer can share the same code.  Photon can be set to offline mode and all the code just works without any changes.  I have tried that out to confirm it and it does.




if (PhotonNetwork.offlineMode)
{
    if (GUILayout.Button("Use Online Mode"))
    {
        PhotonNetwork.offlineMode = false;
    }
}
else
{
    if (GUILayout.Button("Use Offline Mode"))
    {
        PhotonNetwork.offlineMode = true;
    }
}



I added the above code in to the networked Photon Viking demo to try offline single player.

The one missing bit that I would like, is local LAN play for testing multiplayer code while not connected to the Internet.  This is not documented by Exit Games.  They do offline single player or online multiplayer.

There is a solution for offline multiplayer if you have a Windows PC.  It requires installing the server locally.  Photon provide the server executables so you can run your own server.  I don't think it was intended for testing offline but it works.

Photon provide good and quick documentation to get the server installed on a Windows PC so I won't repeat that.

I will just summarize it:

  • Download the server package
  • Copy it all to a folder
  • Run 'Photon Control' from the appropriate folder for your machine.



When I tried it out I was connected to a network.  I ran the 'Load Balancing (My Cloud)' option and set the IP address to Local.  That was just two clicks from the sys tray menus.


I had to initially set the Windows Firewall options to enable network access but that was from an automated Windows popup.  It all worked flawlessly.

I could swap between local and cloud server by changing the settings from the Photon menu:



I used the same demo, side by side but this time it used the local server.




if (!PhotonNetwork.connected)
{
    if (GUILayout.Button("Use Local Cloud"))
    {
        PhotonNetwork.PhotonServerSettings.UseMyServer(
                ServerSettings.DefaultServerAddress, 
                ServerSettings.DefaultMasterPort, 
                PhotonNetwork.PhotonServerSettings.AppID);

        PhotonNetwork.ConnectUsingSettings("v1.0"); 
    }
    else if (GUILayout.Button("Use Internet Cloud"))
    {
        PhotonNetwork.PhotonServerSettings.UseCloud (
                PhotonNetwork.PhotonServerSettings.AppID, 
                 (int)CloudServerRegion.EU);

        PhotonNetwork.ConnectUsingSettings("v1.0");
    }
}



I added the above code in to the networked Photon Viking demo to swap between local and cloud servers.

The above is all that most people will need.

The following is only useful to a very small minority that want to test networking while totally disconnected, such as on a train or in an airplane.

I hit one snag with the local server.  When I had no network connection at all the server does not run. This happens to me every day when I am working on the train.

As far as I can tell this is an oversight in the design. If all the network adapters on a Windows PC are disconnected then there is no IP address for the Photon server to bind to.

There may be some Photon server settings to enable it to work but I got round this quickly by installing the Microsoft Loopback adapter.  That is basically a dummy network interface that is always present. It is intended for testing networks but it does no harm and is included as standard with Windows installs, although not enabled.

For Windows 8 it is installed from Device Manager.
  • Open Device Manager
  • Select the Network Adapters line
  • Action -> Add legacy hardware -> Network Adapters





  • ...Manually Select from a list (It takes a minute to display the list) then select...
  • Microsoft -> Microsoft KM-TEST Loopback Adapter



  • Next, Next, Finish


That will add the extra adapter in to networking but I did not have to do anything with it.

By default this is set to use DHCP but luckily it falls back to Microsoft's
default IP address which is fine.  Just the adapter's presence is enough.



The Photon Server will now always have an IP to use locally.  Remember that IP is only any good for testing and only really necessary when no other network connections are available.

That last little bit may only be useful to a few but there is little if any documentation that I could find on using the server totally disconnected.

I can now run the demos completely offline:



I'm all setup to work on the connection and lobby scenes.

No comments: