Set up P2P transport using OSS
This guide covers the Unreal Engine P2P-specific transport setup and host connection behavior for a matched game session.
For the shared Matchmaking flow, including creating match tickets, handling match results, and joining the game session, see Integrate matchmaking (Unreal). When you reach the host connection step in that guide, choose the P2P tab and use this page for the transport prerequisites.
Plugin dependencies
P2P using OSS requires the full AccelByte OSS plugin suite including the Network Utilities plugin for P2P functionality. For detailed dependency information, see UE Plugin Dependencies Guide.
Prerequisites
-
Configure the match pool to use a session template with the P2P session type. See Configure P2P.
-
Enable Sessions V2 in the AccelByte Online Subsystem (OSS) by adding the following to the
DefaultEngine.inifile:[OnlineSubsystemAccelByte]
bEnableV2Sessions=true -
Enable
AccelByteNetworkUtilitiesby adding the following toDefaultEngine.ini:[AccelByteNetworkUtilities]
UseTurnManager=true
HostCheckTimeout=5
[/Script/AccelByteNetworkUtilities.IpNetDriverAccelByte]
NetConnectionClassName=AccelByteNetworkUtilities.IpConnectionAccelByte
AllowDownloads=false
[/Script/Engine.Engine]
!NetDriverDefinitions=ClearArray
+NetDriverDefinitions=(DefName="GameNetDriver",DriverClassName="/Script/AccelByteNetworkUtilities.IpNetDriverAccelByte",DriverClassNameFallback="/Script/OnlineSubsystemUtils.IpNetDriver")
+NetDriverDefinitions=(DefName="DemoNetDriver",DriverClassName="/Script/Engine.DemoNetDriver",DriverClassNameFallback="/Script/Engine.DemoNetDriver")
Non-seamless travel fail workaround
During non-seamless travel, Unreal Engine's base networking class (UIpConnection) attempts to perform DNS resolution on the AccelByte IP format, even though this format is not a valid DNS hostname. As a result, the resolution fails and produces a network error.
To avoid this issue, set bNonSeamlessTravelUseNewConnection=true in your DefaultEngine.ini file under the [AccelByteNetworkUtilities] section. Enabling this option ensures that DisableAddressResolution() is invoked before the base connection initialization, preventing Unreal Engine from attempting DNS resolution on the AccelByte address.
[AccelByteNetworkUtilities]
bNonSeamlessTravelUseNewConnection=true
Connect after joining a P2P game session
After the shared Matchmaking flow joins the game session, check whether the local player is the P2P host. The host should travel as a listen server. Other members should travel to the resolved P2P connect string.
const FOnlineSessionAccelBytePtr SessionInterface = GetSessionInterface();
check(SessionInterface.IsValid());
FNamedOnlineSession* Session = SessionInterface->GetNamedSession(SessionName);
check(Session != nullptr);
TSharedPtr<FOnlineSessionInfoAccelByteV2> SessionInfo =
StaticCastSharedPtr<FOnlineSessionInfoAccelByteV2>(Session->SessionInfo);
check(SessionInfo.IsValid());
if (SessionInfo->GetServerType() != EAccelByteV2SessionConfigurationServerType::P2P)
{
return;
}
const FUniqueNetIdPtr LocalPlayerId = GetUniquePlayerId();
if (!ensure(LocalPlayerId.IsValid()))
{
return;
}
ULocalPlayer* LocalPlayer = GetLocalPlayer();
if (!ensure(LocalPlayer != nullptr))
{
return;
}
APlayerController* Controller = LocalPlayer->GetPlayerController(GetWorld());
if (!ensure(Controller != nullptr))
{
return;
}
FString TravelUrl{};
if (SessionInterface->GetResolvedConnectString(SessionName, TravelUrl, NAME_GamePort) && !TravelUrl.IsEmpty())
{
if (SessionInterface->IsPlayerP2PHost(LocalPlayerId, SessionName))
{
FString MapName;
Session->SessionSettings.Get(SETTING_MAPNAME, MapName);
Controller->ClientTravel(FString::Printf(TEXT("%s?listen"), *MapName), TRAVEL_Absolute);
}
else
{
Controller->ClientTravel(TravelUrl, TRAVEL_Absolute);
}
}
For debugging purposes, use the Relay (TURN) as the Interactive Connectivity Establishment (ICE) connection by passing the additional parameter -iceforcerelay during the game launch.
Troubleshooting
- To confirm that P2P connection has been established, check the ICE/WebRTC data-channel result from AccelByte Network Utilities. Register
RegisterICERequestConnectFinishedDelegate(...)and treatEAccelByteP2PConnectionStatus::Successas the network-level signal that the peer connection is established. A connected Lobby websocket or a successfulJoinSession()only confirms service/session connectivity; it does not prove that the P2P data channel is connected. For Private Cloud observability, keepbSendMetricAutomatically=trueso Network Utilities sends the TURN connection metric after the ICE connection succeeds. - If
JoinSession()succeeds but travel fails, verify theAccelByteNetworkUtilitiesnet driver configuration and addbNonSeamlessTravelUseNewConnection=truewhen using non-seamless travel. - If clients connect directly but fail when relay is required, verify TURN Manager is enabled, TURN regions are available for the namespace, and run with
-iceforcerelayto reproduce the relay path.