Coming From PUN
Introduction
This article discusses how to get into Fusion when coming from a PUN background; the focus is on object synchronization and gameplay.
While PUN is a vastly successful and easy to use networking solution, it shows its age and inadequacies to handle modern multiplayer games aspects such as higher player counts, precise replication of player actions and handling of authority. Fusion is just as easy to use and should be preferred for most projects.
Differences
There are some differences to look out for when coming from PUN.
Fusion instantiates a Runner
per player and it has to be setup in some scene. To do so, the context-menu of the Hierarchy panel has a Fusion submenu with useful shortcuts to setup scenes.
Fusion can run multiple Runner
instances in one process, which is mostly for testing and debugging. Helper panels in the Editor let you chose which instance is visible and gets input.
When the Editor runs multiple peers at the same time, it will reload the current scene when it starts. Game logic may have to be adjusted to support this. Standalone build can easily connect with the Editor, as in PUN.
Many APIs in PUN were available via the PhotonNetwork
class. Fusion has a Runner
per instance instead. Any class inheriting from SimulationObject
or NetworkObject
have access to the Runner
and Object members, so accessing the Fusion APIs is just as easy as in PUN.
Where PUN only offers "distributed" authority, Fusion supports running as Dedicated Server
, Client Hosted
and Shared Mode
. The Shared Mode
is similar to PUN and authority of Networked objects is distributed to the players. Scene objects are controlled by one player automatically.
Where PUN only has the concept of control for objects, Fusion breaks down authority into state authority and input authority (unless Shared Mode
is used).
Scripts in PUN usually only check photonView.IsMine
to determine if a client controls the object. Fusion keeps track of Object.HasStateAuthority
and Object.HasInputAuthority
separately. Ports from PUN should use the Shared Mode
of Fusion and check HasStateAuthority
.
In PUN, the Player.ActorNumber
goes up for every new player. In Fusion, the PlayerRef
starts at 0 and goes up to MaxPlayers - 1
. If there is a host for a game, that player will always get MaxPlayers - 1
as PlayerRef
value.
Fusion needs to know the scenes of a project. Scenes can be arranged in the project build setup and then imported from there.
Similarities
While the expectation may be that Fusion is vastly different from PUN, many ideas actually carry over.
A key element in PUN is the PhotonView
which has a direct equivalent called NetworkObject
. As in PUN, the NetworkObject is just an identifier and relies on additional components to provide the desired behaviour.
Fusion has replacements for the common components: For example, a PhotonRigidbodyView
can be replaced with a NetworkRigidbody
, the PhotonTransformView
becomes a NetworkTransform
. Both are available as 2D variant, just as in PUN.
The PhotonAnimatorView
can be replaced with a NetworkMecanimAnimator
. For controlling characters specifically, Fusion has a comprehensive NetworkCharacterController
which PUN does not offer.
The individual settings of components are different - in most cases the default values are fine to start. All components on NetworkObject
s and children are found automatically. Fusion fully supports having multiple NetworkObject
s in a hierarchy, where needed.
As in PUN, NetworkObject
s can be placed in a scene or instantiated at runtime. In Fusion, call Runner.Spawn()
instead of PhotonNetwork.Instantiate()
. To load scenes, replace PhotonNetwork.LoadLevel()
with Runner.SetActiveScene()
.
Other important classes in PUN are the MonoBehaviourPun
and MonoBehaviourPunCallbacks
. In Fusion, scripts inherit from NetworkBehaviour
to write game logic and keep state. Scripts can inherit the SimulationBehaviour
, if they will not contain game state. Where PUN called OnPhotonInstantiate()
, Fusion uses the Spawned()
callback to initialize network scripts.
While Custom Properties in PUN were Hashtables with setter methods, Fusion synchronizes plain C# properties instead: As part of a NetworkBehaviour
, auto-implemented properties just need a [Networked]
attribute to become part of the game state. Only the authority of an object can change the values and they are automatically replicated over the network, which means less potential for cheating.
Remote procedure calls (Rpc
s) are also supported and taken to a new level: Put the attribute [Rpc]
on a method and call it as it you call a local method - Fusion will convert the calls to work over the network.
Reference Table
PUN | Fusion |
---|---|
PhotonNetwork | SimulationBehaviour.Runner and SimulationBehaviour.Object |
MonoBehaviourPunCallbacks | SimulationBehaviour and NetworkBehaviour |
PhotonNetwork.AddCallbackTarget(this) | N/A (automatic) |
PhotonNetwork.Instantiate() | Runner.Spawn() |
PhotonView | NetworkObject |
IPunObservable.OnPhotonSerializeView() | C# auto-implemented properties and Input Sync |
PhotonTransformView | NetworkTransform |
PhotonRigidbodyView | NetworkRigidbody |
PhotonAnimatorView | NetworkMecanimAnimator |
N/A | NetworkCharacterController |
[PunRPC] | [Rpc] |
PhotonNetwork.LoadLevel() | Runner.SetActiveScene() |