1 - Lobby

The Animator Tutorial is a Unity3D based tutorial. It will show you how to develop your own multiplayer enabled application powered by Photon Cloud and how to use Characters using Animator for their animations.


Connection to Server, Room Access and Creation

Let's first tackle the core of this tutorial, being able to connect to Photon Cloud server and join a Room or create one if necessary.

  1. Create a new scene, and save it as Launcher.unity.
  2. Create a new c# script Launcher.
  3. Create an empty GameObject in the Hierarchy, named Launcher
  4. Attach the c# script Launcher to the GameObject Launcher.
  5. Edit the c# script Launcher to have its content as below

    Coding Tip: if you are not copying and pasting (which is recommended, because if you do type everything, you will likely remember it better), writing comments is very easy, type /// on the line above a method or a property and you'll have the script editor automatically create a structured comment with for example the <summary> tag.
  6. Save the c# script Launcher

Let's review what's in this script so far, first from a general Unity point-of-view and then looking at the PUN specific calls we make.

  • Namespace:
    While not mandatory, giving a proper namespace to your script prevents clashes with other assets and developers. What if another developer create a class Launcher? Unity will complain, and you or that developer will have to rename the class for Unity to allow the project to be executed. This can be tricky if the conflict comes from an asset you downloaded from the Asset Store. Now, Launcher class is really Com.MyCompany.MyGame.launcher actually under the hood it very unlikely that someone else will us this exact same Namespace because you own this domain and so using reversed domain convention as namespace makes your work safe and well organized. Com.MyCompany.MyGame is supposed to be replaced by your own reversed domain name and game name which is good convention to follow.

  • MonoBehaviour Class:
    Notice that we are deriving our Class with MonoBehaviour which essentially turns our Class into a Unity Component that we can then drop onto a GameObject or Prefab. A Class extending a MonoBehaviour has access to many very important methods and properties. In your case we'll use two callback methods, Awake() and Start().

  • PhotonNetwork.autoJoinLobby

    During Awake(), we set PhotonNetwork.autoJoinLobby to false, because we don't need the Lobby features, we only need to get the list of existing Rooms. This is generally a good idea to force the settings, because in the same project you could have another scene that actually wants to autoJoin the Lobby, and so both cases will be fine within the same project without trouble down the road when switching between the two different approaches.

  • PhotonNetwork.ConnectUsingSettings()

    During Start() we call our public function connect() to PUN Cloud using PhotonNetwork.ConnectUsingSettings(). Notice the _gameVersion variable representing your gameversion. You should leave it to "1" until you need to make breaking changes on a project that is already Live. The important information to remember here is that PhotonNetwork.ConnectUsingSettings() is the starting point for your game to be networked and connect to Photon Cloud.

  • PhotonNetwork.automaticallySyncScene

Our game will have a resizable arena based on the number of players, and to make sure that the loaded scene is the same for every connected player, we'll make use of the very convenient feature provided by Photon: PhotonNetwork.automaticallySyncScene

When this is true, the MasterClient can call PhotonNetwork.LoadLevel() and all connected players will automatically load that same level.

At this point, you can save the Launch Scene and open the PhotonSettings (select it from the Unity menu Window/Photon Unity Networking/Highlight Photon Server Settings), we need to set the debug level to Full in the like so:

Launcher Script Inspector
PhotonSettings debug level Setup

And then we can hit Play. You should see in the Unity Console a good dozens of logs. Look specifically for "Connected to masterserver." log which indicated that indeed we are now connected and ready to join a room for example.

A good habits to have when coding is to always test failure potential. Here we assume the computer is connected to the Internet, but what would happen if the computer isn't connected to the Internet? let's find out. Turn off Internet of your computer and play the Scene. You should see in the Unity console an Error "Connect() to 'ns.exitgames.com' failed: System.Net.Sockets.SocketException: No such host is known".

Ideally, our script should be made aware of this issue and react elegantly to these situation and propose a responsive experience no matter what situation or problem could arise.

Let's now handle both of these case and be informed within our Launcher script that we indeed connected or not to PUN Server. This will be the perfect introduction to PUN Callbacks.

PUN CallBacks

PUN is very flexible with callbacks and offered three very different implementations. Let's cover all three approach for the sake of learning and we'll pick the one that fits best depending on the situation.

"Magic" Methods

When using a regular MonoBehaviour, one can actually simply create private methods.

It's magical because any MonoBehaviour can implement that method or any other message from PUN. It's following the same principal as the main methods Unity is sending to MonoBehaviours like Awake() or Start(). However we are not going to use this, because if you misspell these 'Magic' methods, nothing will inform you about your error, so this is a very fast and practical implementation, but only when know exactly the name of each methods, and that you are well acquainted and expert in debugging techniques to quickly find these kind of issues.

Using IPunCallbacks and IPunObservable Interfaces

PUN is providing two c# Interfaces that you can implement in your class: IPunObservable and IPunCallbacks.

MonoDevelop: Implement Interface Methods
MonoDevelop: Implement Interface Methods

This is a very secure way to make sure a class complies to all the Interface, but forces the developer to implement all the interface declarations. Most good Script Editor will make this task very easy, as demonstrated above when using MonoDevelop. However, the script could end up with a lot of methods that may doing nothing, yet must be all implemented for Unity compiler to be happy. So this is really when your script is going to make heavy use of all or most PUN Features.

We are indeed going to use IPunObservable, further down the tutorial for data serialization.

Using Photon.PunBehaviour

The last technique, which is the one we'll be using often, is the most convenient one. Instead of creating a class that derives from MonoBehaviour, we'll derive the class from Photon.PunBehaviour, as it exposes specific properties and virtual methods for us to use and override at our convenience. It's very practical, because we can be sure that we don't have any typos, and we don't need to implement All methods.

MonoDevelop: Override Method
MonoDevelop: Override Method

Note: when overriding, most script editor will by default implement a base call and fill that up for you automatically, but in our case we don't need to, so as a general rule for Photon.PunBehaviour, never call the base method.

Note: the other great benefit when overriding, is that you benefit from contextual helps by simply hovering over the method name.

So, let's put this in practice with OnConnectedToMaster() and OnDisconnectedFromPhoton() pun callbacks

  1. Edit the c# script Launcher
  2. Modify the base class from MonoBehaviour to Photon.PunBehaviour

  3. Add the following two methods at the end of the class, within a region Photon.PunBehaviour CallBacks for clarity.

  4. Save Launcher script.

Now if we play this scene with or without Internet, we can take the appropriate steps to inform the Player and/or proceed further into the logic. We'll deal with this in the next section when we'll start building the UI. right now we'll deal with the successful connections:

So, we append to the OnConnectedToMaster() method the following call:

As the comment says, we need to be informed if the attempt to join a random room failed, in which case we need to actually create a room, so we implement OnPhotonRandomJoinFailed() PUN callback in our script and create a room using PhotonNetwork.CreateRoom() and, you guessed already, the related PUN callback OnJoinedRoom() which will inform your script when we effectively join a room:

Now if you run the scene, and you should end up following the logical successions of connecting to PUN, attempting to join an existing room, else creating a room and join that newly created room.

At this point of the tutorial, since we have now covered the critical aspects of connecting and joining a room, there are few things not very convenient, and they need to be addressed, sooner than later. These are not really related to learning PUN, however important from an overall perspective.

Expose variables in Unity Inspector

You may already know this, but in case you don't, MonoBehaviours automatically expose their public properties to the Unity Inspector. This is a very important concept within Unity, and in our case we'll modify the way we define the LogLevel and make a public variable so that we can set that up without touching the code itself.

and in the Awake() we'll modify it as follow:

So, now we don't force the script to be of a certain type of LogLevel, we simply need to set it in the Unity inspector, and hit run, no need to open the script, edit it, save it, wait for Unity to recompile and finally run. It's a lot more productive and flexible this way.

We'll do the same for the maximum number of players per room. Hardcoding this within the code isn't the best practice, instead, let's make it as a public variable, so that we can later decide and toy around with that number without the need for recompiling.

at the beginning of the class declaration, within the Public Variables region let's add:

and then we modify the PhotonNetwork.CreateRoom() call and use this new public variable in place of the harcoded number we were using before.

Launcher Script Inspector
Launcher Script Inspector

Back to Content

Next Part.
Previous Part.

 To Document Top