{"id":86675,"date":"2020-03-10T21:14:47","date_gmt":"2020-03-10T21:14:47","guid":{"rendered":"https:\/\/www.red-gate.com\/simple-talk\/?p=86675"},"modified":"2021-07-29T19:44:05","modified_gmt":"2021-07-29T19:44:05","slug":"creating-multiplayer-games-with-unity-and-pun","status":"publish","type":"post","link":"https:\/\/www.red-gate.com\/simple-talk\/development\/dotnet-development\/creating-multiplayer-games-with-unity-and-pun\/","title":{"rendered":"Creating Multiplayer Games with Unity and PUN"},"content":{"rendered":"<p>Playing a game with others across the world is a common desire for the average video game user. In fact, there are some games that don&#8217;t even have a single player mode and opt to be multiplayer only. Creating games is already a complex process, so how does one create their game so it can be played by multiple people at once? For the Unity developer, there is a helpful plugin that makes the multiplayer game creation a much easier process. That plugin is PUN (Photon Unity Networking) created by Exit Games. This plug-in specializes in easing the multiplayer game creation process by handling aspects such as matchmaking, client to server architecture, and cracking down on issues such as latency.<\/p>\n<p>Though PUN does simplify the process, creating any multiplayer game can still be a daunting task. Some projects have been created to help you get started using PUN. The <a href=\"https:\/\/github.com\/prof-smash\/PUNGameWithoutCode\">first project<\/a> is largely codeless, with only the player object&#8217;s movement being programmed ahead of time. All required assets have been created in advance with the only item missing is the plug-in itself. You&#8217;ll see how to add PUN to the project in a moment. The <a href=\"https:\/\/github.com\/prof-smash\/PUNGameComplete\">second project<\/a> is the complete version of what this article covers with all code in their corresponding scripts and the plug-in already imported.<\/p>\n<p>The article will assume that you&#8217;ve downloaded the codeless project. To load it into Unity simply open the Unity Hub application and click the <em>Add <\/em>button as shown in Figure 1.<\/p>\n<p class=\"caption\"><img loading=\"lazy\" decoding=\"async\" width=\"966\" height=\"593\" class=\"wp-image-86676\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2020\/03\/word-image-16.jpeg\" \/><\/p>\n<p class=\"caption\">Figure 1: Adding a new project<\/p>\n<p>Navigate to your project directory and choose <em>Select Folder <\/em>to add it to the list of projects in Unity Hub. Once done, you can open the project and begin.<\/p>\n<h2>Project Overview<\/h2>\n<p>First, it&#8217;s recommended to get familiar with the project. There are two scenes, one title screen and another multiplayer scene. (You can switch between scenes in the Asset window under Scenes.) As you may have guessed, the multiplayer scene is where players can move around and see each other. The title screen consists of a simple user interface that asks the player to join a multiplayer game. Under the hood, there are three controllers in the title screen: the network, room, and lobby controllers. A lobby is typically an area where players can socialize, change their settings, or view the results of the previous game. This project&#8217;s lobby will remain simplistic, with it just being in the title screen and simply handling room creation. Speaking of room creation, a room will be the place where the main multiplayer game takes place. Over in the multiplayer scene, there is only a <em>GameSetup <\/em>object which focuses on the creation of player objects.<\/p>\n<p>There are a total of five scripts that will be worked on throughout the course of this project. Most of these scripts relate to objects in the two scenes such as the <em>LobbyController <\/em>script going to, you guessed it, the <em>LobbyController <\/em>object. You can also see the <em>PhotonPlayer <\/em>prefab placed within <em>Resources PhotonPrefabs<\/em>. This the path that PUN will take to find and spawn the player object. Once the PUN plug-in is added to the project, you&#8217;ll need to come back here and add a few components to <em>PhotonPlayer<\/em>.<\/p>\n<p>Finally, the project is set up in advance to open a resolution dialog. In order to properly test the multiplayer functionality, you&#8217;ll need to run two copies of the game, one in the editor and one from an exe that will be built later. The resolution dialog will give you the option to open the game in windowed mode which will in turn makes the multiplayer functionality easier to view and test. If you want to see how this was put together, navigate to <em>Edit Project Settings <\/em>then select <em>Player <\/em>on the left hand side of the <em>Project Settings<\/em> window. From there make sure you&#8217;re looking at <em>PC, Mac, and Linux Standalone<\/em> settings and have a look at the <em>Resolution and Presentation <\/em>section. Note: according to the Unity editor itself, the resolution dialog will be phased out at some point in the future.<\/p>\n<h2>Photon PUN Setup<\/h2>\n<p>Before getting too deep into the project, you will need to create a Photon app id for the project to connect to the Photon servers. You get this by visiting the Photon website, <a href=\"https:\/\/www.photonengine.com\/\">photonengine.com<\/a>, and either signing in to an existing account or creating a new one. Both options are found under <em>Sign In <\/em>on the website.<\/p>\n<p>After you&#8217;ve logged in, you&#8217;ll be in the apps screen. You will naturally need to create a new app to get an app id, so go ahead and select the <em>Create New App <\/em>button. New accounts will have this button in the center of the screen as shown in Figure 2.<\/p>\n<p class=\"caption\"><img loading=\"lazy\" decoding=\"async\" width=\"310\" height=\"431\" class=\"wp-image-86677\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2020\/03\/word-image-17.jpeg\" \/><\/p>\n<p class=\"caption\">Figure 2: Creating a new Photon app.<\/p>\n<p>Fill out the form, making sure that the <em>Photon Type <\/em>field has <em>Photon PUN <\/em>entered. The name of the project can be whatever you like, and description and url fields are optional. The screen should look something like Figure 3.<\/p>\n<p class=\"caption\"><img loading=\"lazy\" decoding=\"async\" width=\"560\" height=\"769\" class=\"wp-image-86678\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2020\/03\/word-image-18.jpeg\" \/><\/p>\n<p class=\"caption\">Figure 3: App creation screen<\/p>\n<p>After creating the app you&#8217;ll see a new app on the app screen with your app name on it. In it lies the app id shown in Figure 4. Keep this handy, because you will need it shortly.<\/p>\n<p class=\"caption\"><img loading=\"lazy\" decoding=\"async\" width=\"458\" height=\"428\" class=\"wp-image-86679\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2020\/03\/word-image-19.jpeg\" \/><\/p>\n<p class=\"caption\">Figure 4: Getting your app id<\/p>\n<p>With the app id created, you can move on to setting up PUN into Unity itself. To import PUN into Unity you will first need to open the Unity Asset Store, which can be accessed from the top menu by navigating to <em>Window Asset Store<\/em> as shown in Figure 5.<\/p>\n<p class=\"caption\"><img loading=\"lazy\" decoding=\"async\" width=\"389\" height=\"416\" class=\"wp-image-86680\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2020\/03\/word-image-20.jpeg\" \/><\/p>\n<p class=\"caption\">Figure 5: Opening the Asset Store<\/p>\n<p>Once opened, search for PUN in the search bar, then select <em>PUN 2 \u2013 Free<\/em>.<\/p>\n<p class=\"caption\"><img loading=\"lazy\" decoding=\"async\" width=\"647\" height=\"457\" class=\"wp-image-86681\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2020\/03\/word-image-21.jpeg\" \/><\/p>\n<p class=\"caption\">Figure 6: Accessing the PUN plug-in<\/p>\n<p>Click the <em>Download<\/em> button to download the plug-in to your system. After the download is complete, the button will change to <em>Import<\/em>. Click this button and a new window appears showing all the different assets you&#8217;re about to import. If you want to, you can leave out the <em>Demos <\/em>folder, but otherwise be sure to import everything. The plug-in is imported but now a new window has appeared asking for an app id. Copy the app id you received earlier from the Photon website into the app id field in the Unity editor. Then click the <em>Setup Project <\/em>button shown in Figure 7.<\/p>\n<p class=\"caption\"><img loading=\"lazy\" decoding=\"async\" width=\"350\" height=\"268\" class=\"wp-image-86682\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2020\/03\/word-image-22.jpeg\" \/><\/p>\n<p class=\"caption\">Figure 7: Completing the Photon setup<\/p>\n<p>With the app id set up, you are now ready to begin the coding process, starting with the <em>NetworkController <\/em>script. Find the script in the <em>Assets<\/em> window and double-click it to open in Visual Studio.<\/p>\n<h2>NetworkController<\/h2>\n<p>To begin, you will need <code>using Photon.Pun<\/code> at the top of every script, including this one. From there, change <code>NetworkController<\/code>&#8216;s inheritance from <code>MonoBehaviour<\/code> to <code>MonoBehaviourPunCallbacks<\/code>. Then you can either comment out or delete the <code>Update<\/code> method. This takes care of the setup portion of the script. In the <code>Start<\/code> method you enter the following code:<\/p>\n<pre class=\"lang:c# theme:vs2012\">PhotonNetwork.ConnectUsingSettings();<\/pre>\n<p>This code is responsible for connecting the game to the Photon master server using whatever settings are defined in your project. Once the game connects to the server, a simple message will be printed to the Unity console stating which region server the game connected to.<\/p>\n<pre class=\"lang:c# theme:vs2012\">public override void OnConnectedToMaster()\r\n{\r\n\tDebug.Log(\"Connection made to \" + \r\n        PhotonNetwork.CloudRegion + \" server.\");\r\n}<\/pre>\n<p>The server you connect to is based on your location. For instance, in this example the connection is being made to the USA East server, signified by the \u201cus\u201d token. There&#8217;s also USA West (usw), Europe (eu), Canada East (cae), and many others. The full list of regions and corresponding tokens can be found <a href=\"https:\/\/doc.photonengine.com\/en-us\/realtime\/current\/connection-and-authentication\/regions\">here<\/a>.<\/p>\n<p><em>NetworkController <\/em>is now complete. Now is a good time to double check your code using Figure 8 and save your work. When you&#8217;re ready the next script will be <em>LobbyController<\/em>.<\/p>\n<p class=\"caption\"><img loading=\"lazy\" decoding=\"async\" width=\"655\" height=\"331\" class=\"wp-image-86683\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2020\/03\/word-image-23.jpeg\" \/><\/p>\n<p class=\"caption\">Figure 8: The complete <em>NetworkController <\/em>script<\/p>\n<h2>LobbyController<\/h2>\n<p>In addition to <code>Photon.Pun<\/code><em>, <\/em>you&#8217;ll also need <code>using Photon.Realtime<\/code> and <code>using UnityEngine.UI<\/code> to complete this script. Like in <em>NetworkController <\/em>you also must make sure the script is inheriting from <code>MonoBehaviourPunCallbacks<\/code>. As for <code>Start<\/code> and <code>Update<\/code><em>, <\/em>you may delete or comment those out. Then declare the following variables:<\/p>\n<pre class=\"lang:c# theme:vs2012\">[SerializeField]\r\nprivate Text buttonText;\r\n[SerializeField]\r\nprivate int roomSize;\r\nprivate bool connected;\r\nprivate bool starting;<\/pre>\n<p>The <code>buttonText<\/code> and <code>roomSize<\/code> variables were given the <code>SerializeField<\/code> attribute to make them visible to the Unity editor without needing to make the variables public. Then two bools were declared that will help keep track of the game&#8217;s status such as connection to the master server and loading the game room. Speaking of connections, another <code>OnConnectedToMaster<\/code> function is needed in this script, but this one has more going on than in <em>NetworkController<\/em>.<\/p>\n<pre class=\"lang:c# theme:vs2012\">public override void OnConnectedToMaster()\r\n{\r\n\tPhotonNetwork.AutomaticallySyncScene = true;\r\n\tconnected = true;\r\n\tbuttonText.text = \"Begin Game\";\r\n}<\/pre>\n<p>First the game synchronizes the current scene with the Photon network. Then we set <code>connected<\/code> to true and change the <code>buttonText<\/code>&#8216;s text to <em>Begin Game<\/em> where before it would say <em>Loading&#8230;<\/em> as it was trying to connect. Now that the game is connected, the button in the title screen needs to be able to start the game. To do this, you enter the following:<\/p>\n<pre class=\"lang:c# theme:vs2012\">public void GameButton()\r\n{\r\n  if (connected)\r\n    {\r\n        if (!starting)\r\n        {\r\n            starting = true;\r\n            buttonText.text = \"Starting Game. Click Again to Cancel\";\r\n            PhotonNetwork.JoinRandomRoom(); \/\/ attempt joining a room\r\n        }\r\n        else\r\n        {\r\n            starting = false;\r\n            buttonText.text = \"Begin Game\";\r\n            PhotonNetwork.LeaveRoom(); \/\/ cancel the request\r\n        }\r\n    }\r\n    else\r\n        Debug.Log(\"Not connected to server!\");\r\n}<\/pre>\n<p>At the start, the function checks to make sure the game has connected to the master server. If it isn&#8217;t, it&#8217;ll print a message to the debug console. So long as the game is connected it then checks if the game has been told to start. Assuming it hasn&#8217;t, it will begin the game. The button text will change to let the user know that they can cancel the request if desired. Finally, <code>PhotonNetwork.JoinRandomRoom<\/code> will attempt to connect the player to a pre-existing room. Currently, <em>LobbyController <\/em>should look something like Figure 9 below.<\/p>\n<p class=\"caption\"><img loading=\"lazy\" decoding=\"async\" width=\"655\" height=\"646\" class=\"wp-image-86684\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2020\/03\/word-image-24.jpeg\" \/><\/p>\n<p class=\"caption\">Figure 9: The <em>LobbyController <\/em>so far<\/p>\n<p>Of course, you&#8217;re the only one that currently owns a copy of this game at this point. There shouldn&#8217;t be any rooms to join. What do you do then? At that point, you must create your own. First, print out a message letting you know that the game failed to join a room. Then, call a soon to be created method that will create a new room.<\/p>\n<pre class=\"lang:c# theme:vs2012\">public override void OnJoinRandomFailed(short returnCode, string message)\r\n{\r\n\tDebug.Log(\"Failed to join a room... creating room\");\r\n\tCreateRoom();\r\n}<\/pre>\n<p>The room creation process involves getting a random room number. Then the game makes sure the room is visible to other copies of the game in the network, lets it know that the room is open and limits the number of players allowed in the room to the value of <code>roomSize<\/code>. After that&#8217;s set up, the game asks the Photon network to create the game room. In the event that the room number is already taken, a method similar to the one above will be called, and the room creation process will start again.<\/p>\n<pre class=\"lang:c# theme:vs2012\">void CreateRoom()\r\n{\r\n\tDebug.Log(\"Creating room now\");\r\n\tint randomRoomNumber = Random.Range(0, 10000);\r\n\tRoomOptions roomOps = new RoomOptions() { IsVisible = true, \r\n             IsOpen = true, MaxPlayers = (byte)roomSize };\r\n\tPhotonNetwork.CreateRoom(\"Room\" + randomRoomNumber, roomOps); \r\n\tDebug.Log(randomRoomNumber); \r\n}\r\npublic override void OnCreateRoomFailed(short returnCode, \r\n        string message) \r\n{\r\n\tDebug.Log(\"Failed to create room... trying again\"); \r\n\tCreateRoom();\r\n}<\/pre>\n<p><em>LobbyController&#8217;s <\/em>room creation portion of the script should look similar to Figure 10.<\/p>\n<p class=\"caption\"><img loading=\"lazy\" decoding=\"async\" width=\"857\" height=\"363\" class=\"wp-image-86685\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2020\/03\/word-image-25.jpeg\" \/><\/p>\n<p class=\"caption\">Figure 10: The room creation portion of <em>LobbyController<\/em><\/p>\n<p>Everything is now in place for lobby creation, but the game hasn&#8217;t quite started yet. Most of the pieces are in place, but the game won&#8217;t move on to the multiplayer scene from here. This is where <em>RoomController <\/em>will step in. It will help the game properly join the current room and load the scene where the real action takes place.<\/p>\n<h2>RoomController<\/h2>\n<p>Remember to include <code>using Photon.Pun<\/code> and inherit from <code>MonoBehaviourPunCallbacks<\/code><em>. <\/em>In addition, you can also delete or comment out the <code>Start<\/code> and <code>Update<\/code> methods. Then declare a private int, serializing it so you can still edit the value in the Unity editor.<\/p>\n<pre class=\"lang:c# theme:vs2012\">[SerializeField]\r\nprivate int multiplayerSceneIndex;<\/pre>\n<p>Next, you&#8217;ll need to make the script a callback target. This is being done because a callback function in this script will be triggered in the <em>LobbyController <\/em>script. The code to get that setup looks like this:<\/p>\n<pre class=\"lang:c# theme:vs2012\">public override void OnEnable()\r\n{\r\n\tPhotonNetwork.AddCallbackTarget(this);\r\n}\r\npublic override void OnDisable()\r\n{\r\n\tPhotonNetwork.RemoveCallbackTarget(this);\r\n}<\/pre>\n<p>Now with the setup portion out of the way, a new method will be needed for when a room is successfully created. This function will print a message stating that the player has joined a room before calling a <code>StartGame<\/code> method which, as the name implies, will start the game.<\/p>\n<pre class=\"lang:c# theme:vs2012\">public override void OnJoinedRoom()\r\n{\r\n\tDebug.Log(\"Joined Room. Multiplayer game has begun.\");\r\n\tStartGame();\r\n}\r\nprivate void StartGame()\r\n{\r\n\tif (PhotonNetwork.IsMasterClient)\r\n\t{\r\n\t\tDebug.Log(\"Starting Game\");\r\n\t\tPhotonNetwork.LoadLevel(multiplayerSceneIndex);\r\n\t}\r\n}<\/pre>\n<p>In <code>StartGame<\/code><em>, <\/em>you can see that first the game checks if it is the master client (the one hosting the game). If it is, then a message will be printed to the Unity console and the multiplayer scene will be loaded. Scene loading in this instance is a little different from how you might normally load a scene in Unity. It calls <code>LoadLevel<\/code> from the <code>PhotonNetwork<\/code> class and is given the <code>multiplayerSceneIndex<\/code> variable as input. Over in the build settings of the project, there are the two game scenes, the title and multiplayer scene. This list of scenes is like an array, so the title scene is index 0 and the multiplayer scene is index 1. Eventually you&#8217;ll tell Unity what element in the list of scenes to load by giving the <code>multiplayerSceneIndex<\/code> variable a value of 1.<\/p>\n<p>The full <em>RoomController <\/em>script can be seen below in Figure 11.<\/p>\n<p class=\"caption\"><img loading=\"lazy\" decoding=\"async\" width=\"514\" height=\"560\" class=\"wp-image-86686\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2020\/03\/word-image-26.jpeg\" \/><\/p>\n<p class=\"caption\">Figure 11: The complete <em>RoomController <\/em>script<\/p>\n<h2>GameSetupController<\/h2>\n<p>Congratulations! The hardest parts of this project are behind you. It&#8217;s all downhill from here. In the <em>GameSetupController <\/em>script you&#8217;ll want both <code>using Photon.Pun<\/code> and <code>using System.IO<\/code>. This time you do not need to inherit from <code>MonobehaviourPunCallbacks<\/code>, so leave the inheritance as is. You&#8217;ll also want to keep the <em>Start <\/em>method, but you can do whatever you want with <code>Update<\/code>. <code>Start<\/code> does only one thing, and that&#8217;s call a method named <code>CreatePlayer<\/code>. Right below the <code>Start<\/code> method you&#8217;ll create the <code>CreatePlayer<\/code> method proper:<\/p>\n<pre class=\"lang:c# theme:vs2012 \">private void CreatePlayer()\r\n{\r\n\tDebug.Log(\"Creating Player\");\r\n\tPhotonNetwork.Instantiate(Path.Combine(\"PhotonPrefabs\", \r\n            \"PhotonPlayer\"), Vector3.zero, Quaternion.identity);\r\n}<\/pre>\n<p>All this script is doing in the end is creating the player object. The game is told to find this player object under a <em>PhotonPrefabs <\/em>folder and to look for the prefab named <em>PhotonPlayer<\/em>. Everything is setting the starting position and rotation values. The full script can be seen below in Figure 12.<\/p>\n<p class=\"caption\"><img loading=\"lazy\" decoding=\"async\" width=\"895\" height=\"385\" class=\"wp-image-86687\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2020\/03\/word-image-27.jpeg\" \/><\/p>\n<p class=\"caption\">Figure 12: The complete <em>GameSetup <\/em>script<\/p>\n<h2>PlayerMovement<\/h2>\n<p>While most of the <em>PlayerMovement <\/em>script has been setup in advance, there are some parts that are missing. If you were to try to play the game with other players now, you&#8217;d run into an issue where one player could control all the player objects at once. That is an obscene amount of power for one player to have, so some code will be entered in to prevent this issue. Once again, you&#8217;ll need <strong>using <\/strong><code>Photon.Pun<\/code> but you <strong><em>do not<\/em><\/strong> need to inherit from <code>MonobehaviourPunCallbacks<\/code>. Next you need to declare a new variable:<\/p>\n<pre class=\"lang:c# theme:vs2012\">private PhotonView PV;<\/pre>\n<p>Over in the <code>Start<\/code> method you&#8217;ll set the value of <code>PV<\/code> to the player object&#8217;s <code>PhotonView<\/code> component.<\/p>\n<pre class=\"lang:c# theme:vs2012\">void Start()\r\n{\r\n\tPV = GetComponent&lt;PhotonView&gt;();\r\n}<\/pre>\n<p>After that, head to the <code>Update<\/code> method. At the top you&#8217;ll add the following:<\/p>\n<pre class=\"lang:c# theme:vs2012\">if (PV.IsMine)\r\n\tMovement();<\/pre>\n<p>What is a <code>PhotonView<\/code> and how does it help? <code>PhotonView<\/code> is a component that goes to an object. It&#8217;s responsible for identifying objects in the scene. When the component is attached to the player object later, you&#8217;ll effectively give it an id that the network will use to identify which player object goes to what player. In code, this works with the <code>IsMine<\/code> variable. In the above example, you&#8217;re simply checking if the current player belongs to this specific instance of the player object. If it does, then move the object like normal.<\/p>\n<p class=\"caption\"><img loading=\"lazy\" decoding=\"async\" width=\"576\" height=\"582\" class=\"wp-image-86688\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2020\/03\/word-image-28.jpeg\" \/><\/p>\n<p class=\"caption\">Figure 13: The complete <em>PlayerMovement <\/em>script<\/p>\n<h2>Finishing Touches<\/h2>\n<p>All the code for the project is now complete. The various scripts need to go to their corresponding objects, and some modifications need to be made to the <em>PhotonPlayer <\/em>prefab. Starting in the title screen, first add the <em>NetworkController, RoomController, <\/em>and<em> LobbyController <\/em>scripts to their respective objects. Figure 14 shows adding the NetworkController script to the NetworkController object.<\/p>\n<p class=\"caption\"><img loading=\"lazy\" decoding=\"async\" width=\"709\" height=\"616\" class=\"wp-image-86689\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2020\/03\/word-image-29.jpeg\" \/><\/p>\n<p class=\"caption\">Figure 14: Attaching a script to an object<\/p>\n<p>After adding the RoomController script to the <em>RoomController <\/em>object, edit the value of <em>MultiplayerSceneIndex <\/em>to 1 as shown in Figure 15.<\/p>\n<p class=\"caption\"><img loading=\"lazy\" decoding=\"async\" width=\"600\" height=\"131\" class=\"wp-image-86690\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2020\/03\/word-image-30.jpeg\" \/><\/p>\n<p class=\"caption\">Figure 15: Changing the value of <em>Multiplayer Scene Index<\/em><\/p>\n<p>In the <em>LobbyController <\/em>assign a room size limit of your choosing. The example below sets it to four.<\/p>\n<p>Next, fill in the <em>Button Text <\/em>field by expanding (clicking the small arrow) <em>Canvas <\/em>in the <em>Hierarchy <\/em>then expanding <em>GameButton<\/em>. Click and drag the <em>Text <\/em>object into the field as shown in Figure 16.<\/p>\n<p class=\"caption\"><img loading=\"lazy\" decoding=\"async\" width=\"950\" height=\"249\" class=\"wp-image-86691\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2020\/03\/word-image-31.jpeg\" \/><\/p>\n<p class=\"caption\">Figure 16: Editing the values of the <em>Lobby Controller <\/em>script component<\/p>\n<p>Select <em>GameButton <\/em>from the <em>Hierarchy <\/em>and scroll down in the <em>Inspector <\/em>until you see the<em> OnClick <\/em>event. Click the plus button shown in Figure 17 to add a new event.<\/p>\n<p class=\"caption\"><img loading=\"lazy\" decoding=\"async\" width=\"584\" height=\"139\" class=\"wp-image-86692\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2020\/03\/word-image-32.jpeg\" \/><\/p>\n<p class=\"caption\">Figure 17: Creating a new <em>OnClick <\/em>event<\/p>\n<p>Then click and drag the <em>LobbyController <\/em>object from the <em>Hierarchy <\/em>into the <em>Object <\/em>field in <em>OnClick<\/em>.<\/p>\n<p class=\"caption\"><img loading=\"lazy\" decoding=\"async\" width=\"610\" height=\"578\" class=\"wp-image-86693\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2020\/03\/word-image-33.jpeg\" \/><\/p>\n<p class=\"caption\">Figure 18: Specifying <em>LobbyController <\/em><\/p>\n<p>Finally, select the drop-down menu that currently says <em>No Function. <\/em>Navigate to <em>LobbyController GameButton <\/em>to assign the <em>GameButton <\/em>function to this button&#8217;s <em>OnClick <\/em>event. Now, whenever the button is clicked, any code in the <em>GameButton <\/em>function will be performed. Figure 19 shows how to set this up.<\/p>\n<p class=\"caption\"><img loading=\"lazy\" decoding=\"async\" width=\"580\" height=\"614\" class=\"wp-image-86694\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2020\/03\/word-image-34.jpeg\" \/><\/p>\n<p class=\"caption\">Figure 19: Setting the button&#8217;s function<\/p>\n<p>Switch to the Multiplayer scene it by finding it in <em>Assets \uf0e0 Scenes<\/em>. Double-click the Multiplayer scene to switch scenes. Select the <em>GameSetup<\/em> object and attach the <em>GameSetupController <\/em>script as shown in Figure 20.<\/p>\n<p class=\"caption\"><img loading=\"lazy\" decoding=\"async\" width=\"931\" height=\"662\" class=\"wp-image-86695\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2020\/03\/word-image-35.jpeg\" \/><\/p>\n<p class=\"caption\">Figure 20: Setting up the GameSetup object<\/p>\n<p>Finally, in the <em>Assets <\/em>folder navigate to <em>Resources PhotonPrefabs <\/em>and find the <em>PhotonPlayer <\/em>object. Click it and navigate to the <em>Inspector <\/em>window. Two more components will be added to complete the player object. Click the <em>Add Component <\/em>button shown in Figure 21.<\/p>\n<p class=\"caption\"><img loading=\"lazy\" decoding=\"async\" width=\"815\" height=\"388\" class=\"wp-image-86696\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2020\/03\/word-image-36.jpeg\" \/><\/p>\n<p class=\"caption\">Figure 21: Adding new components<\/p>\n<p>In the window that appears, search for <em>Photon View <\/em>and <em>Photon Transform View<\/em> as in Figure 22.<\/p>\n<p class=\"caption\"><img loading=\"lazy\" decoding=\"async\" width=\"526\" height=\"370\" class=\"wp-image-86697\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2020\/03\/word-image-37.jpeg\" \/><\/p>\n<p class=\"caption\">Figure 22: Adding the <em>Photon View <\/em>and <em>Photon Transform View <\/em>components<\/p>\n<p>Click and drag the <em>Photon Transform View <\/em>component into the <em>Observed Components <\/em>box in the <em>Photon View <\/em>component as shown in Figure 23. Once you&#8217;ve finished that, the game is ready to play.<\/p>\n<p class=\"caption\"><img loading=\"lazy\" decoding=\"async\" width=\"611\" height=\"384\" class=\"wp-image-86698\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2020\/03\/word-image-38.jpeg\" \/><\/p>\n<p class=\"caption\">Figure 23: Setting <em>PhotonPlayer&#8217;s Photon Transform View <\/em>component as the observed component<\/p>\n<p>Save your work, navigate to <em>File Build and Run <\/em>from the top menu, and choose where you want the exe file to be saved. Make sure that it is an empty folder. In order to properly test the multiplayer functionality, two copies of the game will need to be opened. One will be run from the editor and another will run from an exe. Make sure the editor version has the title screen opened before playing. As a reminder, you open different scenes in the Unity editor by navigating to the <em>Scenes <\/em>folder in the <em>Assets <\/em>window and double clicking your scene of choice. In this case, the scene you need to open is <em>MenuScene<\/em>. When the exe is finished building, the game will start. A configuration window will appear before the game begins properly. Tinker with the settings as you wish, but it is recommended to at least keep the game in windowed mode so you can easily go back and forth controlling the two games. If everything is correct, there will be two player objects loaded into the multiplayer scene, one being controlled from the editor and one from the exe. Move the player in one game by using the arrow keys and notice that the other game will update accordingly. Figure 24 shows the game in action.<\/p>\n<p class=\"caption\"><img loading=\"lazy\" decoding=\"async\" width=\"1523\" height=\"804\" class=\"wp-image-86699\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2020\/03\/word-image-39.jpeg\" \/> Figure 24: The multiplayer game in action<\/p>\n<h2>Conclusion<\/h2>\n<p>What&#8217;s normally a daunting, difficult to perform task has now been rendered simpler thanks to the PUN plug-in. For those with bigger ambitions for their multiplayer works, this is only the beginning. A simple room and lobby controller were put together with the ability to have multiple players in a game at once. Of course, the game is simplistic in its current state. All the players can do right now is move around the scene. Perhaps they&#8217;ll be fighting each other in some kind of combat situation, or maybe they&#8217;ll work together. At that point, it is up to the creator to decide. Regardless of what the game turns out to be, PUN makes it easier to create.<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Many games today involve more than one player, but creating a multiplayer game is not easy. In this article, Lance Talbert show how the PUN plugin takes care of the difficult parts for you.&hellip;<\/p>\n","protected":false},"author":317499,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[143538,53],"tags":[5134],"coauthors":[52549],"class_list":["post-86675","post","type-post","status-publish","format-standard","hentry","category-dotnet-development","category-featured","tag-sql-prompt"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/86675","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/users\/317499"}],"replies":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/comments?post=86675"}],"version-history":[{"count":3,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/86675\/revisions"}],"predecessor-version":[{"id":86701,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/86675\/revisions\/86701"}],"wp:attachment":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/media?parent=86675"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/categories?post=86675"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/tags?post=86675"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/coauthors?post=86675"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}