This document is about: PUN 2

PUN Classic (v1)、PUN 2 和 Bolt 處於維護模式。 PUN 2 將支援 Unity 2019 至 2022,但不會添加新功能。 當然,您所有的 PUN & Bolt 專案可以用已知性能繼續運行使用。 對於任何即將開始或新的專案:請切換到 Photon Fusion 或 Quantum。

Features Overview


Cloud or OnPremises

PUN clients connect to the Photon Cloud or your own Photon Servers. Even if you plan to host your own servers, the Photon Cloud is a good starting point.

Best Region

The Photon Cloud is hosted in many regions of the world, to distribute players and keep latency low. PUN clients dynamically check the available servers and pick the best one automatically. The client will stick to that region, unless latency gets worse. When the list of regions changed on connect, PUN will reevaluate all regions, too. Fully automatically.

"Best Region" option is not deterministic. Sometimes it may be "random" due to little variations or exact same ping calculations.

Theoretically, you could:

  • have the same exact ping to multiple regions from the same device. So its random, if you end up with different regions on clients connected to the same network.
  • different ping values for the same region on different devices (or different retries on the same device) connected to the same network.

For instance, in the case of "us" and "usw" (or "ru" and "rue"), you could either make use of the online regions whitelist to select the ones you want and drop the others or connect to an explicit region.

Udp, Tcp and WebSockets

PUN supports several Transport Layer protocols, which makes it compatible with most platforms. The default protocol is UDP with a reliability protocol on top. This is fast and flexible. On the other end of the spectrum, WebSockets are used on some platforms as the only supported protocol (e.g. WebGL exports).


Unity Integration

PUN is tightly integrated with Unity. It extends the Editor, makes use of the Inspector and offers the PhotonView component to make Game Objects networked easily.

Versioning by GameVersion

In the Photon Cloud, the GameVersion string is used as simple way to isolate builds (and players) from one another, without changing the AppId. Change the GameVersion when when making breaking changes to the network logic to keep players of different versions apart. PUN will append its PunVersion string to the GameVersion set by you to mitigate potential incompatibilities between PUN versions. Your GameVersion "1.0" becomes "1.0_2.xy" due to this.


Photon makes use of a very simple REST API to integrate any community backend your title should use. With external authentication, you can make use of user accounts, get a user's ID and arbitrary values for the user. You can also block users from connecting, should you need.


PhotonNetwork provides several callbacks to let your game know about state changes, like "connected" or "joined a game". PUN 2 organizes the callbacks in interfaces (for performance reasons) and any class implementing those must register via PhotonNetwork.AddCallbackTarget().

Alternatively, your script may extend MonoBehaviourPunCallbacks which enables you to override each callback method individually. You don't have to call the base implementation in that case.


public class MyClass : MonoBehaviourPunCallbacks 
    public override void OnJoinedRoom()
        Debug.Log(string.Format("OnJoinedRoom() called by PUN: {0}", PhotonNetwork.CurrentRoom.Name));

You can learn more and get your hands on callbacks in the Lobby section of our PUN Basics Tutorial.


Random Matchmaking

Photon's matchmaking approach is very client driven and flexible. Typically, the server selects a suitable, random room by request of a client via PhotonNetwork.JoinRandomRoom(). Various filtering options can be used to narrow down the selection. See our "Matchmaking Guide" for more info on matchmaking.

Lobbies and Room Lists

Lobbies can be used to organize rooms into various lists. Clients may join a lobby to get the list and updates. T he so called "SQL Lobby" supports queries with very flexible "WHERE" filtering. Alternatively, clients can query the server for a subset of the list, to show a pre-filtered selection.

Room Options

When clients create rooms, they can define some of the behaviour of the new room. Of course, the max number of players can be defined. When set to invisible, matchmaking will ignore the room and only users with the room's name can join. You can share the userIDs of the players, define how long a user lingers in the room list after a disconnect and more.

Custom Properties for Matchmaking

Custom Properties of rooms can be used to define and share your own values set. Keys and values are set via Hashtables. This can be used in-game but also for matchmaking. Just define which keys of properties should be available in the matchmaking.

Slot Reservation

When a game is played in teams or parties, players often want to stick together. Photon supports this via "Expected Players": A list of users who will also join a room. Photon's matchmaking reserves a sport per "expected" player.


Networked Objects

Generic GameObjects can be turned into networked objects with a PhotonView component. The PhotonView identifies the object across the network and is used to sync the state of it. Typically, the PhotonView gets attached to a prefab which is instantiated at runtime. Often every player has her own objects to control.

To add a PhotonView to a GameObject, simply select a GameObject and use: "Components/Miscellaneous/Photon View".

photon cloud: photon view
Photon Cloud: Photon View

You can learn more about PhotonViews in the Player Networking section of our PUN Basics Tutorial.


Once in a room, clients can send messages to the other players or selected ones.

Aside from "low level" generic events (see: RaiseEvent), PUN has two specific messaging features: RPCs are method calls executed by all players on a specific networked object and secondly, a PhotonView can observe a script to sync this object's values (position, health, etc.). The observed script needs to implement OnSerializePhotonView.

Where needed, messages can be buffered on the server, which will send them also to players who join later on. This is used, for example, to spawn characters.

You can learn more about RPC Messages in the Player Networking section of our PUN Basics Tutorial.

Mecanim (Animator) Synchronization

PUN offers a component to synchronize the animation state of a character automatically.

You can learn more in the Player Networking section of our PUN Basics Tutorial.

Synchronized Timestamp

Whenever a client connects to a Photon Server, it will synchronize a lag-rectified timestamp. This can be used in a room (as all players are connected to the same Game Server then) to synchronize the timing of events.

Custom Properties

The Custom Properties of Photon Realtime, are a way to sync arbitrary values. They are organized in a simple Hashtable and related to a room or to individual players.

You can learn more about custom properties in the Asteroid Demo, inside the script AsteroidsGameManager.cs.

In-Game Advanced

Compare-And-Swap (CAS)

As everyone is able to set any Custom Property, the game logic might run into concurrency issues. This can be solved with CAS: The new values are only set, if the server's current values match a condition. In short: When everyone tells the server to change a value "from 1 to X", this will only happen once.

Scene PhotonViews

By default, networked objects have the same life-cycle as the player who's instantiating them. If the player leaves, the objects get cleaned up. Scene PhotonViews can be instantiated after loading the scene but they stay in the room, as long as that exists. Of course, networked objects loaded with a scene are also not bound to a player's life-cycle.

You can learn more about Scene Networked Object in the Asteroid Demo, inside the script AsteroidsGameManager.cs.

Scene PhotonViews in multiple scenes

If scenes are loaded additively and these scenes features scene networked objects, make sure to setup the PunSceneSettingsFile scriptableObject asset (in your Project Assets under PhotonUnityNetworking/Pun/code/Editor/) and define, for each of your scene, the minimum view Id to assign: This will guarante that scene networked objects view Ids will not clash as you load scenes additively.

Object-Control Transfer

By default, a networked object is controlled by the client which instantiated it. With ownership transfer, players can request or hand over control of a game object. This changes which client is sending updates (while others consume and apply them).

Interest Groups

The Interest Groups of Photon Realtime (wrapped by PUN), can be used to organize which events a client gets. Based on your logic, clients subscribe to groups and send events to a target group. This can be used for a rudimentary interest management system.

Custom Type Serialization

Photon enables you to define your own de/serialization code for any Type you might want to send via the network. This greatly simplifies how you send data across the network (at the cost of a little overhead).

WebHooks and Persistent Data Strategies

To connect a Photon Server with other services and your own, it uses the concept of WebHooks. Several hooks are pre-defined and can be used to update an external REST-based service.

Turn-Based Games

Two more options for rooms are important for turn-based games: The PlayerTTL defines how long a player will stay "inactive" in a room after a disconnect. The RoomTTL defines how long a room exists, after all players in it disconnected. This way, you can keep rooms and player-spots open for rejoining players.

Performance Options

Pooling Support

PUN allows you to use a simple pool implementation for all networked objects that get instantiated and destroyed. While uncommon in some types of games, this can be a performance-saver in other games.


Alternatively to using a pool, PUN can cache the resources which are loaded to instantiate a prefab (into a networked object). This reduces garbage collection at the cost of memory.


PUN controls at which rate networked objects write (and read) updates. The rate at which updates are being put into messages to be sent, can be set independent from that.

Back to top