This document is about: PUN 2
SWITCH TO

PUN Classic (v1), PUN 2 and Bolt are in maintenance mode. PUN 2 will support Unity 2019 to 2022, but no new features will be added. Of course all your PUN & Bolt projects will continue to work and run with the known performance in the future. For any upcoming or new projects: please switch to Photon Fusion or Quantum.

C# Callbacks

C# SDKs provides callback interfaces that you can implement in your classes:

Photon Realtime C# SDK callbacks interfaces:

  • IConnectionCallbacks: connection related callbacks.
  • IInRoomCallbacks: callbacks that happen inside the room.
  • ILobbyCallbacks: lobby related callbacks.
  • IMatchmakingCallbacks: matchmaking related callbacks.
  • IOnEventCallback: a single callback for any received event. This is 'equivalent' to the C# event LoadBalancingClient.EventReceived.
  • IWebRpcCallback: a single callback for receiving WebRPC operation response.
  • IOnErrorInfoCallback: a single callback for receiving ErrorInfo event.

PUN 2 specific callbacks interfaces:

Other than the Photon Realtime C# ones, PUN 2 adds a few exclusive interfaces.
We will divide them into two groups based on their 'scope' and how they are handled:

  • General callbacks interfaces:

    • IPunInstantiateMagicCallback: a single callback for instantiated PUN prefabs.
    • IPunOwnershipCallbacks: PUN ownership transfer callbacks.
  • PhotonView callbacks interfaces:

    • IPunObservable: PhotonView serialization callbacks.
    • IOnPhotonViewPreNetDestroy: OnPreNetDestroy() callback prior to PhotonView networked object destruction.
    • IOnPhotonViewControllerChange: OnControllerChange() callback when controller changes.
    • IOnPhotonViewOwnerChange: OnOwnerChange() callback when owner changes.

All classes implementing any Photon Realtime or General PUN 2 callbacks interfaces except IPunInstantiateMagicCallback must be registered and unregistered.
Call PhotonNetwork.AddCallbackTarget(this) and PhotonNetwork.RemoveCallbackTarget(this).

All classes implementing any PhotonView callbacks interfaces except IPunObservable must be registered and unregistered.
Call photonView.AddCallbackTarget(this) and photonView.RemoveCallbackTarget(this).
IPunObservable interfaces are handled through the inspector and are not part of the Add/Remove system.

You can implement one or more interfaces per class.
You can also implement the same interface by more than one class.
The price to pay is that classes that implement these interfaces may become too long or have unused methods.

For example in Unity, you could use the MonoBehaviour's OnEnable() and OnDisable() or Start()/Awake() and OnDestroy().

Implementing these interfaces is optional but recommended as we think it can make your code more readable and maintainable.
It also makes the Photon flow and states easier to manage by providing the exact timing to execute some logic.
Other alternatives may require the usage of state flags fields, polling to check client networking state or subscribing to all networking client's status changes or received events or operation responses.
This requires deep knowledge about some internals or low-level Photon details, which you can avoid and focus on your game.

If an unhandled (uncaught) exception occurs in one of the implemented interfaces' callbacks' methods, all other implemented ones for the same interface, same signature and not already called, won't be called. This is due to the fact that we call the implemented interface callback methods of the same signature in a loop in the order of their registration (which could be random in Unity if you register in MonoBehaviour methods).

The reasons behind choosing interfaces over other ways of implementing a callbacks system:

  • making sure callbacks' methods signatures are respected which is guaranteed by the compiler when implementing interfaces
  • grouping callbacks logically related into a single class
  • compared to other methods of providing callbacks, it has less garbage overhead and avoids memory leaks

If you happen to have a method that has the exact signature as one of the callbacks' interfaces' methods or you wish to hide the callbacks methods (unless a cast is made) you could choose explicit interface implementation.

Inheriting from MonoBehaviourPunCallbacks class is the easiest and fastest way to implement PUN2 callbacks:

  • it's a MonoBehaviour that allows you to selectively override the callbacks you need and only those you need
  • no need to remember all the callbacks' interfaces as it implements most of them: IConnectionCallbacks, IMatchmakingCallbacks, IInRoomCallbacks, ILobbyCallbacks, IWebRpcCallback and IOnErrorInfoCallback
  • it already handles callbacks registration and deregistration on your behalf (respectively in OnEnable() and OnDisable())
  • it extends MonoBehaviourPun which exposes the PhotonView easily in a property if the latter is attached to the same GameObject

However, you should be careful as:

  • it does not implement all callbacks interfaces but most. It does not implement IOnEventCallback or PUN specific callbacks. PUN2's utility interfaces are also not implemented e.g. IPunTurnManagerCallbacks
  • if you extend MonoBehaviourPunCallbacks make sure to call the base class methods if you override OnEnable() and OnDisable()
  • MonoBehaviourPunCallbacks.photonView will be null (and useless) if the component is not attached to the same GameObject as a PhotonView
Back to top