This document is about: REALTIME 5
SWITCH TO

Workflow

Code Samples

Below are a few code samples to give you an idea of how the Realtime API is being used. Consider this an overiew but not a complete, working guide. The Quick Start Guide is a more complete project.

Connect

Connecting to the Photon Cloud is easy:

C#

    using Photon.Client;
    using Photon.Realtime;

    var appSettings = new AppSettings() { AppIdRealtime = "<your appid>" };

    var client = new RealtimeClient();
    bool connecting = client.ConnectUsingSettings(appSettings);

The AppIdRealtime is a GUID string, which defines your App / Title for Photon. This is setup in the Photon Dashboard.

ConnectUsingSettings is non-blocking. If there is an obvious issue it will retun false. If all is well, it returns true and you need to "Service" the client and listen to callbacks.

There are a few more options to connect which can be convenient for different cases: For example ConnectUsingSettingsAsync is awaitable and there is also ConnectToRoomAsync which combines connecting with matchmaking.

Call Service

The Realtime API is built to integrate well with any game logic. Internally, incoming and outgoing messages are buffered so your code can define when (and on which thread) incoming messages are handled or outgoing ones are sent.

Call client.Service to dispatch all available incoming messages and send anything outgoing. Calling Service 30x per seconds is common and some apps call it every frame. While the performance impact is low, you still want to tune this to work with your game loop.

C#

void Update()
{
    client.Service();
}

While Service is convenient, there are two methods which can be called instead for more control:

  • Call DispatchIncomingCommands early in the game loop to dispatch a received response or event. The return bool signals if there are (likely) more events to be dispatched. This can be called in a tight loop.
  • Call SendOutgoingCommands after the game wrote updates to send whatever outgoing messages were created and buffered. The returned bool signals if there is more to send.

Service simply calls DispatchIncomingCommands and SendOutgoingCommands as long as each returns true.

Callbacks

Whenever the client can not finish a task immediately, the Realtime API offers callbacks to update the game logic. There are callbacks for changes of the connection (connect, disconnect, etc.), matchmaking events (joined room, left room, etc) and many more.

There is a range of interfaces for callbacks, which group the methods by topic: IConnectionCallbacks, IMatchmakingCallbacks, IOnEventCallback and more. With these implemented, game code can register for callbacks:

C#

public class GameLogic : IInRoomCallbacks, IOnEventCallback, IMatchmakingCallbacks 
{
    // ...

    public GameLogic()
    {
        this.RealtimeClient = new RealtimeClient();
        this.RealtimeClient.AddCallbackTarget(this);
        // ...

        this.RealtimeClient.OpJoinRandomOrCreateRoom(); // uses OnJoinedRoom in case of success
    }

    // ...

    public void OnJoinedRoom()
    {
        // ...
    }

Each method's reference will point out the relevant callbacks for it. They will be called by the game-loop calling Service or a DispatchIncomingCommands loop.

As alternative to the callbacks, there is an async api: Async Extensions.

Async Extensions

Our AsyncExtensions and MatchmakingExtensions provide awaitable methods for the most important jobs a RealtimeClient has: ConnectUsingSettingsAsync, ConnectToNameserverAndWaitForRegionsAsync or ConnectToRoomAsync for example.

The awaitable methods wrap the callbacks and can save a lot of implementation work. In best case, it is a one-liner to connect and join a random room.

Should a task fail, async methods throw a clear exception to handle. This includes runtime errors which you have to expect. For example, ConnectToRoomAsync may fail to join a specific room when it got closed.

C#

    try
    {
        await this.RealtimeClient.ConnectToRoomAsync(mma);
    }
    catch (OperationException e)
    {
        if (e.ErrorCode == ErrorCode.GameClosed)
        {
            // ...
        }
    }

Read the Async Extensions page for more details.

Join Random Room

Typically, players should get into rooms as soon and as easy as possible. With the Realtime API, clients can ask the server to join a random room or create a new one if needs be.

This can be as simple as: OpJoinRandomOrCreateRoom(). The server checks if any rooms accept more players and creates a new one if not. New rooms can be found by the next client looking for a room.

Custom Room Properties (key-value pairs) can be used as filters for random matchmaking. Define "mode", "map" or other keys relevant to your game and have the server find fitting rooms for the players.

There is an extensive Matchmaking Guide and a doc about Custom Properties which can also be used for room state.

Sending Events

Whatever happens on one client can be sent as an event to update everyone in the same room. This is useful to sync state like positions, turns and actions.

C#

byte eventCode = 1; // 1..199; define what the event is about / contains
PhotonHashtable evData = new PhotonHashtable(); // this class avoids some allocations

// add data to the hashtable, then send it:

client.OpRaiseEvent(eventCode, evData, RaiseEventOptions.Default, SendOptions.SendReliable);

Photon will use event codes 200 and up for updates about joining/leaving players, property changes and similar events. You can use event codes below 200 as needed in your game.

The eventData in the example above is a PhotonHashtable. but could also be a byte[] or any data type supported by Photon's serialization (a string, float[], etc.). See Serialization in Photon for more information.

Receiving Events

Whenever an event is dispatched a handler is called. If your class registers for callbacks, implement IOnEventCallback and it also gets events:

C#


// we add IOnEventCallback interface implementation
public class MyClient : IConnectionCallbacks, IMatchmakingCallabacks, IOnEventCallback
{
    // ...

    void IOnEventCallback.OnEvent(EventData photonEvent)
    {
        // we defined two event codes, let's determine what to do
        switch (photonEvent.Code)
        {
            case 1:
                // do something
                break;
            case 2:
                // ...
        }
    }

Each event carries the code and data your clients define and send. Your application knows which content to expect by the code passed (see above).

For an up-to-date list of event codes used by Photon, refer to the EventCode class.

Disconnect

When the application is quitting or when the user logs out do not forget to disconnect.

C#

public class MyClient : IConnectionCallbacks
{
    private RealtimeClient client;

    public MyClient()
    {
        this.client = new RealtimeClient();
        this.client.AddCallbackTarget(this);
    }

    ~MyClient()
    {
        client.Disconnect();
        this.client.RemoveCallbackTarget(this);
    }

    void IConnectionCallbacks.OnDisconnected(DisconnectCause cause)
    {
        switch (cause)
        {
            // ...

Continue to call Service to actually get the callbacks for the disconnect.

Custom or Authoritative Server Logic

The server side logic for the Realtime API is pre-defined for Photon and works the same in all games. This works for a wide range of game types like:

  • First Person Shooters
  • Racing Games
  • Minecraft type of games
  • Casual real-time games and many more.

To prevent cheating and to put the simulation on a central machine, it might make sense to bring game logic to the Photon Servers. This is possible with Photon Server Plugins in which you can intercept, read and write custom events and run logic on them, server side.

Photon Server Plugins are also used by Fusion and Quantum offering a rich API for gameplay features.

Back to top