Connection
App ID and Fusion Settings
Project-wide Fusion configuration lives in UFusionOnlineSubsystemSettings, exposed under Project Settings > Photon in the Unreal editor. The fields read at connect time are AppId, AppVersion, UseLocalServer, LocalServerUrl, and CloudServerUrl. The App ID identifies the project on the Photon Cloud; AppVersion segments players by client build so incompatible versions cannot share rooms; UseLocalServer swaps the cloud endpoint for a local Photon Hive build when developing the server-side plugin against a local relay.
Get an App ID for the project from the Photon Dashboard — the walk-through is in Create a Photon Fusion App ID — and paste it into the App ID field as shown in the Quick Start Guide.
The same settings asset hosts a few fields that belong to other chapters: LoadMapAutomatically shapes the map-load callback sequence (see Map Changes) and DefaultArraySize sets the default capacity for replicated TArray properties (see Replicated Properties).
Connecting to Photon
Every connection and room operation goes through UFusionOnlineSubsystem, a UGameInstanceSubsystem reached the standard Unreal way: GameInstance->GetSubsystem<UFusionOnlineSubsystem>(). The subsystem owns the underlying UFusionClient and the lifecycle of the Fusion session.
The entry point is ConnectToPhoton(FFusionConnectOptions, WorldContextObject). It returns a UFusionConnectToPhotonAsync — a Blueprint latent action with OnSuccess and OnFailure multicast pins. In Blueprints the call appears as the latent node "Connect To Photon"; in C++ the same node is activated explicitly.
C++
UFusionConnectToPhotonAsync* Connect = OnlineSubsystem->ConnectToPhoton(ConnectOpts, this);
Connect->OnSuccess.AddDynamic(this, &UMyGameInstance::HandleConnected);
Connect->OnFailure.AddDynamic(this, &UMyGameInstance::HandleConnectFailed);
Connect->Activate();
Joining or Creating a Room
Once connected, the subsystem exposes five room entry points. CreateRoom, JoinOrCreateRoom, and JoinOrCreateRandomRoom all take an FFusionRoomOptions struct describing the room to create. JoinRoom(RoomName) and JoinRandomRoom join an existing room without creating one — the by-name variant requires the exact room name, the random variant picks any open and visible room.
C++
FFusionRoomOptions RoomOpts;
RoomOpts.RoomName = TEXT("Match-42");
RoomOpts.MaxPlayers = 8;
RoomOpts.PlayerTTL = 60;
RoomOpts.InitialWorld = LobbyWorldPtr;
UFusionJoinOrCreateRoomAsync* Join = OnlineSubsystem->JoinOrCreateRoom(RoomOpts, this);
Join->OnSuccess.AddDynamic(this, &UMyGameInstance::HandleJoined);
Join->Activate();
For the common case of "connect and then join a room in one step", the convenience one-shot ConnectAndJoinRoom(ConnectOptions, RoomOptions, WorldContextObject) chains a UFusionConnectToPhotonAsync and a UFusionJoinOrCreateRoomAsync internally, so application code only binds to one OnSuccess / OnFailure pair.
Prefer JoinOrCreateRoom for invite-style flows where a known room name is shared between players (a friend code, a lobby ID surfaced through an external service). Prefer JoinOrCreateRandomRoom for quick-match flows where the player does not care which room they end up in.
Async Actions
Every connect and room call returns a UFusionRoomActionBase subclass — a Blueprint latent action that exposes OnSuccess and OnFailure multicast delegates as exec pins in BP and as FMulticastDynamicDelegate members in C++. OnFailure carries an EFusionActionFailureCodes value describing the reason.
| Async class | Subsystem method | Wraps |
|---|---|---|
UFusionConnectToPhotonAsync |
ConnectToPhoton |
Initial cloud connection |
UFusionDisconnectFromPhotonAsync |
DisconnectFromPhoton |
Full disconnect from the cloud |
UFusionJoinOrCreateRoomAsync |
JoinOrCreateRoom, JoinOrCreateRandomRoom |
Join a matching room or create one |
UFusionCreateRoomAsync |
CreateRoom |
Create a new room unconditionally |
UFusionJoinRoomAsync |
JoinRoom, JoinRandomRoom |
Join an existing room |
UFusionLeaveRoomAsync |
LeaveRoom |
Leave the current room, stay connected |
UFusionConnectAndJoinRoomAsync |
ConnectAndJoinRoom |
Connect plus join in one action |
EFusionActionFailureCodes covers the practical failure cases: TimeOut, InvalidRegion, ClientAlreadyExists, Disconnected, and the in-progress states Connecting, JoiningRoom, and InRoom — which fire when an action is attempted while another action of the same kind is still mid-flight.
Connection Options and Regions
FFusionConnectOptions carries two fields. Region is a region code string such as "us" or "eu" — see Regions for the full list. RegionSelectionMode is an EFusionRegionSelectionMode enum that decides how the Region field is interpreted.
| Mode | Behavior |
|---|---|
Default |
Use the first available region. The Region string is ignored. |
Select |
Connect to the region named in the Region string. |
Best |
Ping every available region, pick the lowest-RTT one, and cache the result. |
C++
FFusionConnectOptions ConnectOpts;
ConnectOpts.Region = TEXT("us");
ConnectOpts.RegionSelectionMode = EFusionRegionSelectionMode::Select;
For production, ship with Best on first launch so the player lands on the lowest-RTT region without any UI. Persist the chosen region and switch to Select with that value on subsequent launches to skip the ping pass.
Room Options
FFusionRoomOptions describes the room being created or joined.
| Field | Type | Effect |
|---|---|---|
RoomName |
FString |
Unique name within the App ID. Required for invite-style flows; auto-generated when joining randomly. |
MaxPlayers |
int32 |
Maximum concurrent players in the room. |
bIsOpen |
bool |
If false, the room rejects new joins. Set false to seal a match in progress. |
bIsVisible |
bool |
If false, the room does not appear in random-join results. Invite-only rooms set this false. |
EmptyTTL |
int32 (seconds) |
How long the room survives after the last player leaves. Converted to ms internally. |
PlayerTTL |
int32 (seconds) |
How long a disconnected player can rejoin into their old slot. Converted to ms internally. |
InitialWorld |
TSoftObjectPtr<UWorld> |
World to load when the local player joins. Skips a separate ChangeWorld call on the Master Client. |
C++
FFusionRoomOptions RoomOpts;
RoomOpts.RoomName = TEXT("Match-42");
RoomOpts.MaxPlayers = 8;
RoomOpts.PlayerTTL = 60;
RoomOpts.EmptyTTL = 0;
RoomOpts.InitialWorld = LobbyWorldPtr;
Set InitialWorld whenever the room creator already knows the starting map. The local client loads that world automatically as it joins, and the Master Client does not need to issue a separate ChangeWorld call after OnSuccess.
Lobbies and Matchmaking Filters
FFusionRoomOptions does not expose lobby properties or a custom-property filter. There is no equivalent of a lobby_properties dictionary, no custom-keys filter, and no filter expression on the random-join path.
The built-in matchmaking surface is JoinRandomRoom and JoinOrCreateRandomRoom, which pick any room that is bIsOpen=true and bIsVisible=true, without further filter criteria.
For projects that need richer matchmaking, the conversion seam where Fusion's FFusionRoomOptions becomes the Photon Hive's create-room call is FusionMatchmakingHelpers::CreatePhotonRoomOptions. Custom matchmaking criteria can be plumbed through there in conjunction with a parallel surface on the server-side Photon Hive plugin.
Leaving the Room and Reconnecting
LeaveRoom(WorldContextObject) returns a UFusionLeaveRoomAsync and optionally accepts a LobbyWorld soft pointer. When LobbyWorld is set, the client streams back into that world after OnSuccess fires, so the player lands on a clean offline level rather than on the now-detached networked map.
After OnSuccess the client is back in EFusionStatus::Connected. It can call JoinOrCreateRoom again without re-running ConnectToPhoton. For a full teardown of the Photon connection, use DisconnectFromPhoton, which returns the client to EFusionStatus::None.
Tune PlayerTTL together with LeaveRoom flows. PlayerTTL on the original room governs how long a dropped client can rejoin into its old player slot — a LeaveRoom followed by a rejoin within the TTL preserves the player's APlayerState and any PlayerAttached ownership.
Connection Status and Events
Status() returns the current EFusionStatus. The normal lifecycle traces None → Connecting → Connected → JoiningRoom → InRoom → LeavingRoom, with Disconnected and Error reachable from any non-terminal state. The transitions are introduced in Concepts.
| Query | Returns |
|---|---|
IsConnected() |
True when the client has reached at least Connected. |
IsInRoom() |
True when the client is fully in a room (InRoom). |
IsJoiningOrInRoom() |
True for both JoiningRoom and InRoom — useful for "session is forming or formed" gates. |
IsMasterClient() |
True when this client is the elected Master Client of the current room. |
PlayerCount() |
Current number of players in the room. |
GetLocalPlayerId() |
Stable int32 id of the local player for this session. |
GetRtt() |
Round-trip time to the Photon relay, in milliseconds. |
CurrentRoomInfo(Name, Players) |
Room name and current player count as out params. |
The one global event in this chapter is OnConnectedToPhoton, a multicast on UFusionOnlineSubsystem that fires once the initial cloud connection is up. Per-action success and failure are surfaced through the OnSuccess and OnFailure pins on the async nodes — there is no global OnRoomJoined multicast, since the async-action pins already cover that case.
C++
void UMyGameInstance::Init()
{
Super::Init();
OnlineSubsystem = GetSubsystem<UFusionOnlineSubsystem>();
OnlineSubsystem->OnConnectedToPhoton.AddDynamic(this, &UMyGameInstance::HandleConnected);
}
Back to top