Photon is a real-time multiplayer game development framework which has server and cloud services. Games are hosted in globally distributed Photon Cloud so we do not need to worry about hosting. All the operations related to multiplayer functionality are handled by Photon. Free version of PUN comes with 20 CCU subscription but you can upgrade it as you need it. More info can be found on their official site (https://www.photonengine.com/en-US/Photon).
In this tutorial we are going to cover in detail the integration of Photon Unity Networking (PUN) with Unity.
In this tutorial we are using Unity 5.6.3.
This tutorial covers following major things:
Configure game on photon
Setup photon in Unity project
Manage connection with photon
Synchronization of players
Configure Game on Photon
Step-1 : Login to account
We need an account on Photon to configure our game .Go to https://www.photonengine.com/en-US/Photon. Log in to your account if you already have otherwise you can click on Register to create new account.
[Login with Your id on Photon]
Step-2 : Create and configure game
Provide necessary info related to your game and create game.
Step-3 : Get your App Id from dashboard
[Get app id]
We have completed the setup on Photon side.
Setup Photon in Unity Project
Before we start, download the PUN package from the Asset store (https://www.assetstore.unity3d.com/en/#!/content/1786). After download, open PUN settings to configure the project for photon. You can find PUN settings under window -> Photon Unity Networking -> Highlight server settings.
It will open a setting wizard that allows to configure project with photon. Add your app in in the App id field of PhotonServerSettings. Set your appropriate region. Check AutoJoinLobby so photon will automatically join the player in the lobby.
[Photon Server Settings]
Manage connection with Photon
Create a new script called PUNManager and add it to an empty gameobject. Using this script we will handle all server side operations. First of all, we need to connect with Photon. This will enable us to host and join rooms of our game based on the AppID. Call PhotonNetwork.ConnectUsingSettings () method to make connection. We can pass the version number of the game as a string in the argument. Import namespace Photon.
Use following code to connect your project with photon:
To check status whether we are connected or not, take a Text and show status using PhotonNetwork. connectionStateDetailed. After connection, photon will automatically join player in a lobby. When a player joins a lobby OnJoinedLobby callback is called. After that we need to connect to a room. PhotonNetwork.JoinRandomRoom is allow to connect players in a random available room. If no room available it will create a new one. We can also use PhotonNetwork.JoinRoom to connect if we already know the room name. In this tutorial we will use JoinRandomRoom. We will create a button that will handle this event. Add the JoinRoom method in buttons click event in Inspector. After connecting to a room, the function OnJoinedRoom is called.
Add following code to PUNManager script:
As now we are able to connect multiple players, add some game coding to the project. Create a plane and position it with (0, -0.5f, 0). Create a cube, name it Player. Create a script PlayerManager that will handle players’ movements.
Add following code in PlayerManager:
Add this script to Player gameobject. Next, add the Photon view component to the player object (Component > Photon View).
This will enable us to send data packages over the network to synchronize the player. Observe option is automatically set to “reliable delta compressed”. This means that synchronized data will be sent automatically, but only if its value changed. So for example if you move as a player, your position will be updated on the server. By setting it to “off” there is no automatic synchronization at all and you have to do it manually. Drag the transform component into the observe field. At the bottom the field serialization is now added, where you can state which values from the transform to synchronize. Set its value to “Only Position”. In the project hierarchy, create a folder called “Resources”. In it, place the player object from the scene to make it a prefab. This is needed to instantiate the object on the network. In the PUNManager-script add a public game object variable for the player prefab. When OnJoinedRoom() is called, we want to create the player object. Instantiating on a Photon network requires the prefab to be placed in the Resources folder. The prefab parameter for PhotonNetwork.Instantiate() is a string instead of a gameobject. Also create a gameobject plane that can be activated when connected to room.
Make a build of project and run both. You can control both players movement, not just your own. To Solve this issue, we need to check is this a player that instantiated the object? To implement this , we need to check whether the object on the network “is mine” in the player script. Add using Photon; namespace and replace Monobehaviour class with PunBehaviour:
Again make a build and test your code. You can now control only one of the players.
For synchronization between players, photon provides a callback OnPhotonSerializeView() that constantly updates values over the network. This method is useful to sync data that changes often like player movement.
Go to the Photon view component on the player’s prefab. The observed field contains the component that will be synchronized. Drag the component of the player script in the observed field.
Add OnPhotonSerializeView() to the player script.
This function is automatically called every time it either sends or receives data. If the user is the one updating the object, he/she writes to the stream. The clients receive the stream and can apply the data that was send to the object. In the example below, the user sends the transform’s position with stream.SendNext() and this is received by the clients with stream.ReceiveNext(). The order of data send should be the same as the order in which the data is received, otherwise values will get mixed up.
Remote Procedure Calls
Another method of network communication is Remote Procedure Calls (RPCs), which is more useful for data that does not constantly change. This approach is only able to send integers, floats, strings, vectors and quaternions. An RPC is sent by calling photonView.RPC(), in which you define the function name and parameters. Also the Photon targets are required: “PhotonTargets.All” sends the data to all players including local player, “PhotonTargets.OthersBuffered” to everyone in the room except yourself. Add [PunRPC] before function implementation to make it a Remote Procedure Call. To implement this we will create a method that will change the color of the material of your own player.
Add following lines of code in PlayerManager script:
To send data to all the players in room we need to use PhotonTargets. All as target when calling a RPC method. Take a Text and a button that will handle this event. Add PhotonView component to the PUNManager gameobject from Component > Photon View. Create a method named ChangeTextColor and add it in button click event in inspector.
Add the following code in the PUNManager script:
Make a new build and test it. Click on the “Change color ” button and you can see that the text color is changing on both side.
Now create another build and if you run the game, you will see the player’s colors can be changed. Also you can see the other player’s movement.
You can find the complete code here: