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.

Leave a rating/review
Download materials
Save for later
Share
You are currently viewing page 3 of 4 of this article. Click here to view the first page.

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:

  1. When the MainArena scene is loaded, check whether the client is the Master or not. If they are, Instantiate the Car GameObject using PhotonNetwork.Instantiate, change the name of player1 GameObject and also Instantiate the ball GameObject. Otherwise just Instantiate the player2 GameObject and change its name.
  2. Add a PUN Callback method that will take care of various use cases based on network conditions and events.
  3. 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:

  1. 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.
  2. Get a reference to the local Player (the player that is controlling the client), and check whether it is the Master client.
  3. 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 the player1 GameObject.
  4. Similarly, Instantiate the Ball GameObject so that it’s the same Ball GameObject that’s loaded on all clients connected to the current room.
  5. If the client is not the Master, load the Player GameObject from the Resources folder and save a reference to it in the player2 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:

  1. Add Photon Transform View component.
  2. Set the Observe Option to Unreliable on Change.
  3. 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!