step3b_spawnplayers-1024x558

How to create an online multiplayer game with Photon Unity Networking

We are looking for a Unity C# Developer and Node.js/Back-end Developer to join our team. You can find the vacancies here!

In this tutorial we will create a small online multiplayer game using Photon Unity Networking (PUN). This project will be similar to “How to create an online multiplayer game with Unity”, but instead of the standard Unity networking, we will use PUN.

Photon is a real-time multiplayer game development framework which has server and cloud services. Even though the networking implementation of the Kickstarter demo for LFG: The Fork of Truth was build with Unity networking, it was build with PUN in the back of our minds. An advantage of Photon is that it does not require hosting, so the player who created the room can leave the game without causing crashes at the clients. Also, PUN is more stable and the source code is available to fix any issues you might have. An important note is that the free version of Photon requires Unity Pro for iOS and Android. With Photon Plus a free Unity licence is sufficient.

For our projects, we prefer to implement the networking functionality early during development. This means for each new feature, we make sure it also works over the network. In the end this saves us a lot of time, because implementing it at a later stage results in changing a lot of code. To follow this tutorial, a basic understanding of Unity and C# is required.

These are the things we are going to talk about:

  1. Installing the Photon Unity Networking package
  2. Implement server creation and joining an existing host.
  3. Spawning as a player and how objects can be created on the network.
  4. Network communication using State Synchronization and Remote Procedure Calls.
  5. Interpolating and predicting values between data packages.

More tutorials can be found on their official website.

Installation

Before we can get into the code, we need to install PUN. You can find it here on the Asset Store. This package also contains several demos, which are not required for this tutorial, but can give you a nice idea what the possibilities are.

Once the project is downloaded, open the PUN Wizard (Window > Photon Unity Networking). Fill in your email and press send. You will receive a mail with a link to your account which contains an AppID. Copy this ID and paste it in the field “Your AppID”, set your cloud region and save these settings.

Network connection

Create a new script called NetworkManager and add it to an empty object in the scene. This script will handle the network connection and spawn connected players.

When we start the game, we want to connect to the Photon network. This will enable us to host and join rooms of our game based on the AppID. For the function call PhotonNetwork.ConnectUsingSettings() we can add the version number of the game as a string.

void Start()
    {
        PhotonNetwork.ConnectUsingSettings("0.1");
    }

The boolean PhotonNetwork.connected only checks if we are connected to the Photon network itself, not if we are connected to another player’s server. As long as we’re not connected a text label is drawn to show us what the status is.

After the connection has been established, we need to connect to a room. A room can be created with the function call PhotonNetwork.CreateRoom(), where you have to define a unique room name. In the example below an unique ID is added to the name. Other parameters can be used to hide or close the room or set the maximum number of players.

For all rooms in the list, a button is added so it can be joined. This list is updated via the network message OnReceivedRoomListUpdate(), which is called automatically every time a room is added or removed.

After connecting to a room, either by creating or joining one, the function OnJoinedRoom() is called. Add a debug log here so we can see whether we are actually connected.

private const string roomName = "RoomName";
private RoomInfo[] roomsList;

void OnGUI()
{
    if (!PhotonNetwork.connected)
    {
        GUILayout.Label(PhotonNetwork.connectionStateDetailed.ToString());
    }
    else if (PhotonNetwork.room == null)
    {
        // Create Room
        if (GUI.Button(new Rect(100, 100, 250, 100), "Start Server"))
            PhotonNetwork.CreateRoom(roomName + Guid.NewGuid().ToString("N"), true, true, 5);

        // Join Room
        if (roomsList != null)
        {
            for (int i = 0; i < roomsList.Length; i++)
            {
                if (GUI.Button(new Rect(100, 250 + (110 * i), 250, 100), "Join " + roomsList[i].name))
                    PhotonNetwork.JoinRoom(roomsList[i].name);
            }
        }
    }
}

void OnReceivedRoomListUpdate()
{
    roomsList = PhotonNetwork.GetRoomList();
}
void OnJoinedRoom()
{
    Debug.Log("Connected to Room");
}

This is a good point to do our first test. One thing to note is that testing multiplayer takes a bit longer, particularly because you always require two instances of the game. To run two instances, create a new build. Afterwards launch the game and press “Start Server”. Now we can test our new functionality in the Unity editor. After refreshing your list, another button should appear allowing you to connect the two instances of your game.

Spawning a player

Now that we are able to connect multiple players, we can extend the code with game mechanics.

Set up a simple scene with a floor plane, player and some lighting. Add a rigidbody to the player and freeze the rotations, so we will not get strange behaviour while moving.

Create a Player-script, add it to the player object and add the following code:

public class Player : MonoBehaviour
{
    public float speed = 10f;

    void Update()
    {
        InputMovement();
    }

    void InputMovement()
    {
        if (Input.GetKey(KeyCode.W))
            rigidbody.MovePosition(rigidbody.position + Vector3.forward * speed * Time.deltaTime);

        if (Input.GetKey(KeyCode.S))
            rigidbody.MovePosition(rigidbody.position - Vector3.forward * speed * Time.deltaTime);

        if (Input.GetKey(KeyCode.D))
            rigidbody.MovePosition(rigidbody.position + Vector3.right * speed * Time.deltaTime);

        if (Input.GetKey(KeyCode.A))
            rigidbody.MovePosition(rigidbody.position - Vector3.right * speed * Time.deltaTime);
    }
}

Next, add the Photon view component to the player object (Component > Miscellaneous > 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. For now set it to “reliable”. 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 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 NetworkManager-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 game object.

public GameObject playerPrefab;

void OnJoinedRoom()
{
 // Spawn player
 PhotonNetwork.Instantiate(playerPrefab.name, Vector3.up * 5, Quaternion.identity, 0);
}

Time for another test! Create a new build and run two instances again. You will notice that you can control all players connected, not just your own. This shows one important aspect that will be used often when creating a multiplayer game: who controls what object?

One way to fix this problem is to build in a check on the player code so it only receives input from the user that instantiated the object. Because we set reliable synchronization on the network view, data is sent automatically across the network and no other information is required. To implement this method, we need to check whether the object on the network “is mine” in the player script. In the player script change “Monobehaviour” to “Photon.Monobehaviour” to allow Photon networking in this class.

public class Player : Photon.MonoBehaviour
{
    ...

    void Update()
    {
        if (photonView.isMine)
            InputMovement();
    }

    ....
}

If you do another test now, you will see you can only control one of the players.

Another solution could be to send all input to the server, which will convert your data to actual movement and send back your new position to everyone on the network. The advantage is that everything is synchronized on the server. This prevents players from cheating on their local client. A disadvantage of this method is the latency between the client and server, which may result in the user having to wait to see the performed actions.

State Synchronization

There are two methods of network communication. The first is State Synchronization and the other is Remote Procedure Calls, which will be covered in another paragraph. State Synchronization constantly updates values over the network. This approach is useful for data that changes often, like player movement. In
OnPhotonSerializeView() the variables are sent or received and will synchronize them quick and simple. To show you how this works, we will write the code that synchronizes the player’s position.

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 so we can write our own synchronization method.

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 writes to the stream. This occurs automatically based on the sendrate. The clients receive the stream and can apply the data that was send to the object. In the example below, the user sends the rigidbody’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.

void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info)
{
    if (stream.isWriting)
        stream.SendNext(rigidbody.position);
    else
        rigidbody.position = (Vector3)stream.ReceiveNext();
}

Make another build and run it. The results should be the same as before, but now we have granted ourselves control over the movement and how the synchronization works.

Interpolation

You might have noticed latency issues between the two instances due to the sendrate. To smooth the transition from the old to the new data values and fix these latency issues, interpolation can be used. There are several options how this can be implemented. For this tutorial, we will interpolate between the current position and the new position received after synchronization.

OnPhotonSerializeView() needs to be extended to store all the required data: the current position, new position and delay between updates.

private float lastSynchronizationTime = 0f;
private float syncDelay = 0f;
private float syncTime = 0f;
private Vector3 syncStartPosition = Vector3.zero;
private Vector3 syncEndPosition = Vector3.zero;

void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info)
{
    if (stream.isWriting)
    {
        stream.SendNext(rigidbody.position);
    }
    else
    {
        syncEndPosition = (Vector3)stream.ReceiveNext();
        syncStartPosition = rigidbody.position;

        syncTime = 0f;
        syncDelay = Time.time - lastSynchronizationTime;
        lastSynchronizationTime = Time.time;
    }
}

We had a check in Update() whether the object is controlled by the player. If this is not the case, we will use interpolation between the synchronized values.

void Update()
{
    if (photonView.isMine)
    {
        InputMovement();
    }
    else
    {
        SyncedMovement();
    }
}

private void SyncedMovement()
{
    syncTime += Time.deltaTime;
    rigidbody.position = Vector3.Lerp(syncStartPosition, syncEndPosition, syncTime / syncDelay);
}

Create a new build and test it, you should now see the transition looks better between updates.

Prediction

Though the transitions look smooth, you notice a small delay between the input and the actual movement. This is because the position is updated after the new data is received. Until we invent time travel, all we can do is predict what is going to happen based on the old data.

One method to predict the next position is by taking the velocity into account. A more accurate end position can be calculated by adding the velocity multiplied by the delay.

void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info)
{
    if (stream.isWriting)
    {
        stream.SendNext(rigidbody.position);
        stream.SendNext(rigidbody.velocity);
    }
    else
    {
        Vector3 syncPosition = (Vector3)stream.ReceiveNext();
        Vector3 syncVelocity = (Vector3)stream.ReceiveNext();

        syncTime = 0f;
        syncDelay = Time.time - lastSynchronizationTime;
        lastSynchronizationTime = Time.time;

        syncEndPosition = syncPosition + syncVelocity * syncDelay;
        syncStartPosition = rigidbody.position;
    }
}

After building and testing the game again, you will notice the transitions are smooth and the latency between your input and the actual movement seem less. There are also a few corner-cases where behaviour might seem a little strange if the latency is too high. If the player starts moving, the other clients still predict you would stand still. Set the sendrate at network settings back to 15 updates per second for better results.

For our Kickstarter demo, we used a navmesh to walk around and this seemed to make interpolation and prediction better. The sendrate was set to 5 and as a user you could barely notice the delay. This tutorial will not go any deeper into the integration of the navmesh, but for your future projects it might be worth to consider this approach.

Remote Procedure Calls

Another method of network communication is Remote Procedure Calls (RPCs), which is more useful for data that does not constantly change. A good example where we used these in our Kickstarter demo is dialog. In this paragraph we will change the color of a player over the network.

What RPCs do is a function call on a network view component and this component searches the correct RPC function. By adding [RPC] in front of the function, it can be called over the network. This approach is only able to send integers, floats, strings, vectors and quaternions. So not all parameters can be sent, but this can be solved. For example a color can be send by converting it to a vector or quaternion.

An RPC is sent by calling photonView.RPC(), in which you define the function name and parameters. Also the Photon targets are required: “Server” sends the data to the server only, “Others” to everyone on the server except yourself and “All” sends it to everyone. The last two also have the functionality to set is as buffered, this results in newly connected players receiving all these buffered values. Because we send this data package every frame now, there is no need to buffer it.

To integrate this functionality to our tutorial game, Update() needs to call the function to check for input and change the material to a random color. The RPC function changes the color based on the input and if the player object is controlled by the user, he will send an RPC to all others on the network.

void Update()
{
    if (photonView.isMine)
    {
        InputMovement();
        InputColorChange();
    }
    else
    {
        SyncedMovement();
    }
}

private void InputColorChange()
{
    if (Input.GetKeyDown(KeyCode.R))
        ChangeColorTo(new Vector3(Random.Range(0f, 1f), Random.Range(0f, 1f), Random.Range(0f, 1f)));
}

[RPC] void ChangeColorTo(Vector3 color)
{
    renderer.material.color = new Color(color.x, color.y, color.z, 1f);

    if (photonView.isMine)
        photonView.RPC("ChangeColorTo", PhotonTargets.OthersBuffered, color);
}

Now create another build and if you run the game, you will see the player’s colors can be changed.

Conclusion

I hope you enjoyed reading this short tutorial about Photon Unity Networking.

The game now contains the functionality to create or join a Photon room, instantiate a player after the connecting is established, and move around individually. With these techniques you should be able to extend the game with other mechanics, like player rotations and shooting projectiles.

If you have any questions, suggestions or comments, feel free to use the comment section below.

68 Comments
  • How to create an online multiplayer game with Unity » Paladin Studios
    Posted at 17:36h, 08 May Reply

    […] this tutorial I explain how to create a online multiplayer game using Photon Unity Networking (PUN), instead of […]

  • axxe78Luciano
    Posted at 11:24h, 17 May Reply

    Very clean and straight to the point! Thank you very much.

  • Oleg (@olegwn)
    Posted at 14:47h, 17 May Reply

    Thank you very much for this tutorial!

    Got the following compilations error starting from the second code snippet:

    Assets/Scripts/NetworkManagerPUN.cs(22,35): warning CS0618: `PhotonNetwork.CreateRoom(string, bool, bool, int)’ is obsolete: `Use overload with RoomOptions and TypedLobby parameters.’

    Assets/Scripts/NetworkManagerPUN.cs(30,43): error CS1503: Argument `#1′ cannot convert `RoomInfo’ expression to type `string’

    Assets/Scripts/NetworkManagerPUN.cs(30,43): error CS1503: Argument `#1′ cannot convert `RoomInfo’ expression to type `string’

    I’m using PUN+ v 1.25.2

  • Oleg (@olegwn)
    Posted at 14:56h, 17 May Reply

    ok seems like PhotonNetwork.JoinRoom(roomsList[i]); should be –>
    PhotonNetwork.JoinRoom(roomsList[i]).name;

    • Jens van de Water
      Posted at 08:46h, 19 May Reply

      @Oleg thanks for the notification, will change it in the post

  • Léviathan
    Posted at 11:44h, 22 May Reply

    PhotonNetwork.CreateRoom(roomName + Guid.NewGuid().ToString(“N”), true, true, 5);

  • Léviathan
    Posted at 11:45h, 22 May Reply

    warning CS0618: `PhotonNetwork.CreateRoom(string, bool, bool, int)’ is obsolete: `Use overload with RoomOptions and TypedLobby parameters.’

    PhotonNetwork.CreateRoom(roomName + Guid.NewGuid().ToString(“N”), true, true, 5);

    How i can fix it ?

    • Ryan
      Posted at 04:23h, 20 July Reply

      I’m getting this error too. Any ideas??

      • AXE
        Posted at 09:06h, 21 July Reply

        PhotonNetwork.CreateRoom(roomName + Guid.NewGuid().ToString(“N”), new RoomOptions() { maxPlayers = 10}, null);

        • ryan
          Posted at 15:07h, 21 July Reply

          Thank you good sir!

  • grantdillonreid
    Posted at 03:11h, 01 June Reply

    Hey all,

    Had some trouble with the – Guid.NewGuid().ToString”(N”) – line and may have found a solution. Instead tried this and it seemed to work:

    PhotonNetwork.CreateRoom(roomName + System.Guid.NewGuid().ToString(“N”), true, true, 5);

    Thanks and let me know if you find anything similar!

    (Thanks for the great post!)

  • greg
    Posted at 19:02h, 27 June Reply

    this no longer works? when i do the first step i get errors

    • rileydabozo
      Posted at 04:30h, 05 July Reply

      Still works for me, did you download Photon stuff?

  • rileydabozo
    Posted at 04:58h, 05 July Reply

    When finished, and twoi people are in the game, it shows two squares, but one never moves, one is yours, then when the other player moves his it shows a flashing box moving

  • rileydabozo
    Posted at 01:34h, 07 July Reply

    There is no “reliable” option on Photon View. Did you mean Reliable Data Compressed?

    • Jens
      Posted at 10:42h, 14 July Reply

      Yes, sorry for the confusion.

  • Siddharth Trivedi
    Posted at 07:15h, 16 July Reply

    First very nice tutorial series but I have question regarding OnPhotonSerializeView() method. It doesn’t called every time for me. I can’t able to understand paragraph written above it. Please help me in implementation.

    • Nael
      Posted at 00:57h, 16 November Reply

      It’s probably because you need to have the Player script as being observed by the PhotonView, just drag it into the field the same way you did for the transform. Hope this helps

  • Eric
    Posted at 02:50h, 25 July Reply

    I need some help over here. What is &lt? Where can I read a little about it?

  • ryan
    Posted at 03:45h, 25 July Reply

    That’s just the keyboard code for the lessthan ( < ) sign.

  • Claudio Fernandes
    Posted at 16:22h, 29 July Reply

    Very good your text you should be congratulated, I wonder why when a new player connects to the server, I see all the objects in the center, then en sigida osvejo being taken to the correct spots in the world.

    • Claudio Fernandes
      Posted at 22:06h, 29 July Reply

      one more question, this works only for network lan or also works for a web server, type LOL.

    • heemun
      Posted at 12:01h, 11 August Reply

      I have the same problem. How to solve it?

  • m0rgul
    Posted at 16:55h, 22 August Reply

    I am actually working on some sort of MMO game and I stumbled upon PUN, it seems nice so I decided to use this.

    So far so good 😛 I created 2 scenes, the first is a character customization screen, the second is some sort of an arena where the characters can punch each other in the face.

    In the first scene I can select between a male or a female character, chose from 3 wardrobes and color their wardrobes. Upon hitting Save, I store these options in a custom object, serialize the object and store it in PlayerPrefs. I load up the next scene and I’m supposed to apply the options to the spawned character…however…

    The prefabs for the players are 1 generic male with 3 wardrobes equiped (subobjects – I pick one and destroy the other two, then apply the color to the chosen one). My problem was (before I came here) that I would see my character as I customized it, but the other characters I just saw as the default prefab.

    I actually went through your tutorial with the cubes and it seems to be working well, but I do have one question: if we call the RPC on update, isn’t that somewhat unnecessary? Doesn’t it generate a lot of traffic for nothing? I tried calling the RPC on start, but apparently it doesn’t work like that.

    • chris73it
      Posted at 20:37h, 24 August Reply

      Hi m0rgul, did you say you typed the code in this tutorial and it is working fine for you?

      Unfortunately, it doesn’t seem to work for me. It looks like I am having similar issues that also rileydabozo: “When finished, and two people are in the game, it shows two squares, but one never moves, one is yours, then when the other player moves his it shows a flashing box moving”, and Claudio Fernandes: “Very good your text you should be congratulated, I wonder why when a new player connects to the server, I see all the objects in the center, then immediately being taken to the correct spots in the world.” (I very slightly edited both posts.)

      This is what I see:
      (1) I start the server and one cube is present in the center of the plane.
      (2) I can WASD around the cube with no problems and no visible glitches.
      (3) In another window I can join the existing room spawned in (1) and a second cube appears in the center of the plane.
      (4) Now things look visually incorrect: when I move the first cube, I see the cube appearing in the correct position in the second window, but as soon as I stop WASD-ing around the first cube in the second window immediately moves back to the center of the plane. Viceversa, when I move the second cube, I see it flashing in the first window, but as soon as I stop WASD-ing it around, it goes back to the center of the first window.

      Reading articles over the internet, I think I am hitting the issue that PhysX runs independently in both processes (associated to the the windows mentioned above) and they tend to overwrite the position of each other’s cubes. Did you modify the code in this tutorial to fix the issue I just described? If so, can you please share the solution? RIght now, as far as I can tell, this tutorial is nice up to a certain point, and then is conceptually broken.

      • m0rgul
        Posted at 23:46h, 24 August Reply

        Yes, it is working for me…furthermore, I managed to solve my own problem using things from this tutorial (tho there is still one thing I haven’t been able to do, and that is make an RPC with more than one parameter – i was trying to send an integer and a Vector 3 and…no luck, I just split that into two functions and it works).

        The one problem that I did have was the fact that after spawning the second cube, the first one started falling through the plane…To this moment I still have no idea why, but I don’t really need to know anyway 😛

  • chris73it
    Posted at 00:13h, 25 August Reply

    Hi m0rgul,

    are you on a PC or a Mac? And what version of Unity are you using? And, is it PRO?

    Thank you again! Chris

    • m0rgul
      Posted at 10:11h, 25 August Reply

      I’m on a PC, Windows 8 and Unity Pro 4.5.3 I think

  • Zion
    Posted at 13:14h, 27 August Reply

    Nice tutorial by the way. I have been using Unity and Photon to make a multiplayer game where players can run around and bump into eachother real time. At the moment I am running the physics through the Rigidbody class but it’s not responding to collisions properly. I was thinking about RPCs to register major events like player collisions. Is there any chance you can write something about handling real time collisions over a network?

  • chris73it
    Posted at 07:07h, 02 September Reply

    Thank you m0rgul!

    I restarted from scratch a new project and this time it worked flawlessly 🙂

  • Andrei Elvis
    Posted at 19:20h, 15 September Reply

    Assets/Scripts/NetworkManager.cs(30,72): error CS0201: Only assignment, call, increment, decrement, and new object expressions can be used as a statement

    ERROR

  • Andrei Elvis
    Posted at 20:54h, 15 September Reply

    Not working for me!!

  • sunny
    Posted at 15:33h, 23 September Reply

    please help on this….i couldnt run RPC using Photonview

    using UnityEngine;
    using System.Collections;
    public class Example_PhotonView : Photon.MonoBehaviour
    {

    void OnGUI()
    {

    // if the space key is pressed, and this photon view belongs
    //to the local player, call the RPC
    if (GUILayout.Button (“Connect”, GUILayout.Width (100f))) {
    if (photonView.isMine) {

    photonView.RPC (“TestRPC”, PhotonTargets.All);
    }
    else
    {
    Debug.Log(“false”);
    }
    }
    }

    [RPC]
    void TestRPC()
    {
    Debug.Log( “An RPC was called!” );
    }
    void OnPhotonSerializeView( PhotonStream stream,
    PhotonMessageInfo info )
    {
    if( stream.isWriting )
    {
    // writing to the stream, send position
    stream.SendNext( transform.position );
    }
    else
    {
    // reading from the stream, get position
    transform.position = (Vector3)stream.ReceiveNext();
    }
    }
    }

  • aanim
    Posted at 08:47h, 08 October Reply

    this tut is helped to know basic photon networking in unity, thought this case as http://doc.exitgames.com/en/pun/current/tutorials/tutorial-marco-polo

  • Jocko
    Posted at 23:39h, 17 October Reply

    All I get with this tutorial is a damn flashing box for the second player as soon as the synching/smoothing code goes in.

    Nice try – but useless

  • Jocko
    Posted at 20:58h, 23 October Reply

    For all those who are having problems with the ‘flashing’ box/player – here’s what to do:

    Make sure you have dragged the ‘PlayerScript’ COMPONENT into the Photonview ‘Observe box’ Component – don’t just drag the player prefab ( player prefab first, followed by the script component).

    The box should stop flashing and behave properly.

    Other than that irritating omission – this is a good tutorial.

    Thanks.

    • Riz
      Posted at 16:49h, 01 November Reply

      Jocko,I was trying to drag the PlayerScript component into the Photonview ‘Observe box’ Component ,but when I put the cursor on the Observe box appears a prohibition sign .
      I’m desperate,do you know how to fix it ?

      • George
        Posted at 17:21h, 23 November Reply

        Hi had the same – its solved now – in inspector where there is the ThirdNetworkController Script – CLICK on the whole square in inspector and drag it to the Observe filed.. it will work, enjoy

  • Warner Sandrock
    Posted at 01:06h, 24 October Reply

    How to create an online multiplayer game with Photon Unity Networking – Paladin Studios

    […]My 4s did same thing. When you get to the end reboot and stuck in Pangu welcome loop plug your head phones into headphone jack and wait, it will break the loop and finish jailbreak… Do it, seriously!!![…]

  • Dennis
    Posted at 10:44h, 15 November Reply

    The script is full of errors. Please put the full script in here for us. The other tutorial without PUN works just fine but this is just crap

  • Dennis
    Posted at 11:37h, 15 November Reply

    I searched the web for this issue and more people have problems with it. And weird thing is that PhotonNetwork.CreateRoom(roomName + Guid.NewGuid().ToString(“N”), true, true, 5); gives problem at GUID, and there are people that also have this line and it works with them, I have downloaded the PUN from asset store but still don’t work. It’s fixing error after error, that’s why better put a working basic script online. Even the first 4 lines at beginning of this tutorial don’t compile. All is C# so i am not working in a java script.

    • jeyrkh
      Posted at 16:51h, 22 February Reply

      You need to add a Using System; or change it to System.Guid.NewGuid().ToString(:N”)

  • MajorBulldozer
    Posted at 12:55h, 20 April Reply

    Thanks a lot!

  • Sarathi
    Posted at 14:46h, 01 May Reply

    Hi,
    I can only see one player object on both instance of the game. However I can able tomove the 2nd game instance player from first instance. But can’t see the 2nd player.

  • Giddy
    Posted at 21:48h, 26 May Reply

    I met some bug if more than 2 players join in a room.
    After the third player spawning it just flies away.
    How can I fix it?

  • Febi Mudiyanto
    Posted at 14:53h, 30 May Reply

    very nice,, may i ask your simple multiplayer game project?
    i want learn it for my project., please contact me to my email,. (mudiyantofebi@gmail.com) thank you.

  • Popo
    Posted at 20:44h, 19 June Reply

    Is this an example of an authoritative or non-authoritative server?

  • Devarshi
    Posted at 12:51h, 19 July Reply

    great tutorial…learnt a lo…thanks (y)

  • Marshall
    Posted at 16:05h, 03 August Reply

    Hi, I’m having a problem. I followed through the tutorial and did synchronization and everything however, when I play with two windows, I can’t see the other player moving. He just sits there on the other screen when I move him.

  • bert
    Posted at 18:23h, 04 August Reply

    When I run the built version, and a test version in unity (by pressing play) it doesn’t find the existing room, and Debug.Log(roomsList); always returns null even if a room exists

    • jordecoJordy
      Posted at 10:30h, 27 August Reply

      I’m having the same problem, if you can solve it, please contact

  • theOtherHolmes
    Posted at 22:34h, 30 August Reply

    Same problem as previous two posts, I think. I’m at the stage of the tutorial where it says this: “Afterwards launch the game and press ‘Start Server’. Now we can test our new functionality in the Unity editor. After refreshing your list, another button should appear allowing you to connect the two instances of your game.” I made a test build version, started it, clicked “Start Server,” and that button goes away, but nothing changes on the instance of the app running through the Unity editor (still has its own “Start Server” button). How does the “refreshing your list” part happen?

  • Dennis
    Posted at 13:17h, 04 September Reply

    It doesn’t work anymore in unity 5
    All it does is run 2 instances appart from eachother… They do not join eachother.

    NOT WORKING SINCE UNITY 5

    • Donavan White
      Posted at 12:25h, 14 September Reply

      This will work fine in Unity 5, for Photon to setup the lobby correctly so the room list will exist, add the following to your NetworkManager.cs

      https://gist.github.com/anonymous/64d091c63cb41d345a19

      Specifically defining the TypedLobby and adding the OnConnectedToMaster callback that then calls JoinLobby(lobbyName), don’t forget to also add lobbyName to the last argument on CreateRoom. I’ve used the updated syntax for CreateRoom as well since the way in this how-to has since been deprecated.

      • Ram
        Posted at 23:16h, 14 February Reply

        Thanks for that!

      • Neal Chakraborty
        Posted at 09:15h, 06 September Reply

        Hello Donavan White.. Thanks a lot for the code. Now can you please tell me how can I create more than one room with different users.. I am not able to create rooms after the 1st launch..

  • someamerican
    Posted at 22:25h, 15 November Reply

    Tons of errors in the second snippet of the tutorial.
    -1

  • cc10cc10
    Posted at 00:14h, 17 November Reply

    Excuse me to say it like that but your code is crap. There’s a bunch of errors in it.

  • Jonie
    Posted at 01:13h, 09 January Reply

    Hello and sorry for stupid question. I’m complete your example. it’s really good. And now I want to replace my cubes to FirstPersonController from asset. Unfortunately. What I doing wrong? How to make it to work? Guess that problem in PhotonView.isMain() function but I cannot how to add it to my first person player. Whole day and nothing.

  • Towtow10
    Posted at 08:29h, 02 February Reply

    On the 2nd piece of code under Network Connection where do I place it?

  • ankit dave
    Posted at 13:21h, 03 March Reply

    hey friends i can’t destroy my gameobject.
    i made one simple pong game it work perfect on one player but in two player how can i destroy my ball which is prefab when it collides to empty gameobject
    i tried PhotonNetwork.Destroy() but it is not working so i used punrpc

    code is like

    [PunRPC]
    void balldestroyed(string playerprefabname)
    {
    Destroy(ball_obj);
    }

    void OnTriggerEnter(Collider other)
    {
    if (other.tag == “ball”)
    {
    score += 1;
    PhotonView viewobj = PhotonView.Get(this);
    viewobj.RPC(“balldestroyed”, PhotonTargets.All,”Ball”);

    }
    }
    please help me thanks

  • Create Online Game Tutorial | Pagamely Games
    Posted at 01:35h, 06 March Reply

    […] How to create an online multiplayer game with Photon Unity … – In this tutorial we will create a small online multiplayer game using Photon Unity Networking (PUN). This project will be similar to “How to create an online … […]

  • Create Online Game Tutorial | KundgameKundgame
    Posted at 15:18h, 08 March Reply

    […] How to create an online multiplayer game with Photon … – In this tutorial we will create a small online multiplayer game using Photon Unity Networking (PUN). This project will be similar to “How to create an online … […]

  • Ping
    Posted at 11:54h, 12 April Reply

    I’ve followed all the steps given here with the help of the comments, I made it work using Unity 5. But the movements are still delayed. Any solution for this one?

  • Mateo
    Posted at 16:56h, 21 August Reply

    Hello! I am trying to shoot in direction of Mouse Pos. But teh result always is the same – in some situations Bullet goes to a little bit different pos and the collision is detected on each client in different position. Could someone help me ?

  • n2kmaster
    Posted at 00:21h, 05 September Reply

    Anyone know of a sample that is a little more friendly by chance. A beginner like myself gets discouraged instantly when it comes to the coding of unity. I’ve gotten the photon networking, looked at the samples even but trying any of it out…. nope. Never works for me. Even paid to get ripped off on fiverr for a guy to look at that angry bots multiplayer sample for me to change it from top down to fps and no go at all still 2 months later.

  • Henry Choi
    Posted at 11:04h, 06 September Reply

    I am having a bit strange situation happen. I download and load up PUN at first, typed in all the scripts and I exit Unity. After that, when I startup Unity again, the PUN functions in Component and Window menu went missing and could not load the PUN functions again. Is there anyone have the same issue ?

  • Kief
    Posted at 15:27h, 25 October Reply

    Doesn’t work, too many errors, fail.

    guid.newguid doesn’t work, tried all suggestions in comments, just doesn’t fit together right, useless tutorial.

Post A Comment