Introduction to Multiplayer Games With Unity and Photon
Learn how to make your own multiplayer game with Unity and the Photon Unity Networking (PUN) library. By Gur Raunaq Singh.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
Introduction to Multiplayer Games With Unity and Photon
25 mins
Using the Photon Transform View Component
With the room joining code done, the next important Photon Unity Networking concept you need to know is the Photon View Component.
PUN makes it very easy to make a Prefab whose properties (Position, Rotation, etc.) have to be synced across the network during a multiplayer game using the Photon View Component.
An important concept to understand about using PUN is that a Prefab that should get instantiated over the network has to be inside a folder named Resources.
An important side effect of having Prefabs inside Resources folders is that you need to watch their names. You should not have two Prefabs under your Assets’ Resources paths named the same, because Unity will simply pick the first one it finds.
With that out of the way, let’s get started building the Game Manager.
Open the GameManager.cs script in Assets / RW / Scripts.
Here’s an overview of what the GameManager.cs script is going to do:
- When the MainArena scene is loaded, check whether the client is the Master or not. If they are, Instantiate the
Car
GameObject usingPhotonNetwork.Instantiate
, change the name ofplayer1
GameObject and also Instantiate theball
GameObject. Otherwise just Instantiate theplayer2
GameObject and change its name. - Add a PUN Callback method that will take care of various use cases based on network conditions and events.
- Helper methods will Disable UI, Quit Room, etc.
Add the following code after the comment // Start Method
:
// Start Method
void Start()
{
if (!PhotonNetwork.IsConnected) // 1
{
SceneManager.LoadScene("Launcher");
return;
}
if (PlayerManager.LocalPlayerInstance == null)
{
if (PhotonNetwork.IsMasterClient) // 2
{
Debug.Log("Instantiating Player 1");
// 3
player1 = PhotonNetwork.Instantiate("Car",
player1SpawnPosition.transform.position,
player1SpawnPosition.transform.rotation, 0);
// 4
ball = PhotonNetwork.Instantiate("Ball",
ballSpawnTransform.transform.position,
ballSpawnTransform.transform.rotation, 0);
ball.name = "Ball";
}
else // 5
{
player2 = PhotonNetwork.Instantiate("Car",
player2SpawnPosition.transform.position,
player2SpawnPosition.transform.rotation, 0);
}
}
}
Here’s how this works:
- Check whether the client is connected to the Photon Network or not. In case there are some issues with the network, then the Launcher scene should get loaded so that the client can try to connect again.
- Get a reference to the local Player (the player that is controlling the client), and check whether it is the Master client.
- If it is, Instantiate the Player GameObject from the Resources folder (which you will do in the next step) using the
PhotonNetwork.Instantiate
, and save a reference to it in theplayer1
GameObject. - Similarly, Instantiate the
Ball
GameObject so that it’s the same Ball GameObject that’s loaded on all clients connected to the current room. - If the client is not the Master, load the
Player
GameObject from the Resources folder and save a reference to it in theplayer2
GameObject.
Save the file and get back to the Editor.
Now that you have the logic ready to Instantiate the Player and Ball GameObjects, the next step is to add the required components so they can be Instantiated using the PhotonNetwork.Instantiate
method.
From the Project Window, double-click Car prefab in Assets / RW / Prefabs
to open it in Prefab Editing mode.
In the Inspector, you should be able to see that some basic components for a Car GameObject (Rigidbody, Collider, Movements, etc.) are already part of the prefab.
Since only the Transform properties of the GameObject need to be synchronized across the network, add the Photon Transform View component to the Car GameObject.
You’ll notice that a Photon View component is also added, as the Photon Transform View component inherits a lot of properties from it.
In addition to synchronizing the position, rotation and scale of a GameObject, Photon Transform View gives you many different options to make synchronized values appear smooth even when the data is received only a couple of times per second.
In the Inspector, set the Observe option to Unreliable on change in the Photon View Component. This will ensure there’s a smooth transition between the Car Transform values.
Also, add the Car prefab to the Observed Components list in the Photon View component so that its selected Transform properties (seen as selected in Photon Transform View component) are synchronized.
Save the Car prefab.
Next, open the Ball prefab from Assets / RW / Prefabs in Prefab Editing mode and repeat the above steps:
- Add Photon Transform View component.
- Set the Observe Option to Unreliable on Change.
- Add the Ball prefab in the Observed Components list in the Photon View component.
Finally, move the Car and Ball prefabs from Assets / RW / Prefabs to Assets / RW / Resources, so that they can be loaded by the PhotonNetwork.Instantiate
method.
Time to test!
Select File ▸ Build and Run to build an executable binary for your Operating System.
This time:
- Enter a different player name in both clients.
- Enter the same Room name.
- Click the Load Arena button from the Master client.
You should see that the MainArena scene is loaded with 2 Players (cars) and a Ball. You can use the WASD
or the Arrow keys
on your keyboard to move the car around in the arena.
Notice only the 1 car moves in both clients (the car that belongs to the client).
You can also see that both the position of the players and the ball are synchronized in both clients.
All the work is done by Photon Transform View Component that you added to the Car and Ball prefabs.
However, if you close one of the clients, the other client is left unstable. To handle cases like this, you’ll add callback methods to perform the necessary action based on the present situation of a client (such as a network loss or the other player left).
Adding PUN Callback Methods
Add the following code in GameManager.cs after the comment // Update Method
:
// Update Method
void Update()
{
if (Input.GetKeyDown(KeyCode.Escape)) //1
{
Application.Quit();
}
}
This is fairly straightforward.
At any point in the game, if the Escape
button is pressed, call Application.Quit
.
Next, add the following code after the comment // Photon Methods
:
// Photon Methods
public override void OnPlayerLeftRoom(Player other)
{
Debug.Log("OnPlayerLeftRoom() " + other.NickName); // seen when other disconnects
if (PhotonNetwork.IsMasterClient)
{
PhotonNetwork.LoadLevel("Launcher");
}
}
OnPlayerLeftRoom
is a PUN callback method that gets called whenever a Player leaves the room, either by closing the client or getting disconnected from the network.
Finally, add the following code after the comment // Helper Methods
:
// Helper Methods
public void QuitRoom()
{
Application.Quit();
}
When Canvas / Top Menu Panel / Quit Room Button
is clicked, this method will be called.
Finally set the On Click () event of Quit Room Button to GameManager.QuitRoom
.
And that’s it!
You can build a final binary for your Operating System and start playing!