OnlineSubsystem

OnlineSubsystem is the base abstraction layer to build other online services upon such as Steam, PlayFab or Epic Online Services

Updated over 3 years ago

Online Subsystem

Online Subsystem and its interfaces exist to provide a clear abstraction to common online functionality across the available set of platforms in a given environment, one of the main goals is Portability. By default you'll use the OnlineSubsystemNULL, this allows you to host LAN Sessions, so you can find Sessions via a Server List and join them in your LAN network or join directly via IP.

What it doesn't allow you is to host such a Session on the Internet, because you have no Master Server that provides the Client with a list of Servers-Sessions. Subsystems, like for example Steam, will allow you to host Servers-Session that are visible over the Internet, this is important to understand. You can also create your own Subsystem & Master Server, but that requires a lot of coding outside of Unreal Engine.

Online Subsystem Module

Basic Design

Base module Online Subsystem is responsible for regulating how platform specific modules are defined and registered with the Engine. All access to a platform service will go through this module. When loaded, this module will in turn try to load the default platform server module specified in the DefaultEngine.ini file.

[OnlineSubsystem]
DefaultPlatformService = <Default Platform Identifier>

If successful, this default online interface will be available via the static accessor when no parameter is specified.

static IOnlineSubsystem* GetSubsystem(const UWorld* World, const FName& SubsystemName = NAME_None)
    {
#if UE_EDITOR // at present, multiple worlds are only possible in the editor
     FName Identifier = SubsystemName; 
     if (World != NULL)
     {
            IOnlineSubsystemUtils* Utils = GetUtils();
            Identifier = Utils->GetOnlineIdentifier(World, SubsystemName);
     }

     return IOnlineSubsystem::Get(Identifier); 
#else
     return IOnlineSubsystem::Get(SubsystemName); 
#endif
}

Additional services are loaded on demand when called from this function with a proper identifier.

Use of Delegates

Online Subsystem will make heavy use of Delegates when calling functions with Asynchronous side effects. It is important to respect the Delegates and wait for the proper Delegate to be called before calling functions further down the chain. Failure to wait for an Asynchronous task can cause crashes and unexpected, undefined behavior. Waiting for Delegates is especially important during connectivity failures such as a cable pull or other disconnect events.

Amount of time a task may take to finish may seem instantaneous in the ideal case, but can be upwards to almost a minute in the timeout case. The Delegate interface is fairly straightforward, with each Delegate clearly defined at the top of each interface header. Every Delegate has an Add, Clear, and Trigger function. (Although Triggering delegates manually is discouraged). Common practice is to Add() the Delegate right before calling the appropriate function, and then Clear() the Delegate from within itself.

Interfaces

Not all platforms will implement all Interfaces and Game Coding should plan accordinly.

  • Profile

    Interface definition for the online services Profile services. Profile services are defined as anything related to a given User Profile and its associated metadata (Online Presence, Access Permissions, etc).

  • Friends

    Interface definition for the online services Friends services. Friends services are anything related to the Maintenance of Friends and Friends Lists.

  • Sessions

    Interface definition for the online services Session services.Session services are defined as anything related managing a Session and its state.

  • Shared Cloud

    Provides the Interface for sharing files already on the cloud (see User Cloud with other users)

  • User Cloud

    Provides the Interface for per User Cloud file storage.

  • Leaderboards

    Provides the Interface for accessing online Leaderboards

  • Voice

    Provides the Interface for Voice Communication over network while in the game

  • Achievements

    Provides the Interface for Reading/Writing/Unlocking Achievements.

  • External UI

    Provides the Interface for accessing a given platform's external Interfaces if available.

Sessions and Matchmaking

Matchmaking is the process of matching Players with Sessions. A Session is basically an Instance of the Game running on the Server with a given set of properties, which is either advertised, so that it can be found and joined by Players wanting to play the Game, or private, so only Players who are invited or notified of it in some way can join. Picture an Online Game Lobby that lists all of the Games currently being played, each game in the list is a Session, or individual online match. Players are matched with Sessions either by searching or some other means and then join the Session to play the Match.

Basic Lifetime of a Session

Create a new Session with desired Settings

wait for Players to request to join the Match

Register players who want to join

Start the Session

Play the Match

End the Session

Unregister the Players (Update the Session if you want to change the Type of Match and go back to waiting for Players to join or Destroy the Session)

Session Interface

Session Interface, IOnlineSession, provides platform-specific functionality for setting up the pieces behind the scenes that are necessary in order to perform Matchmaking as well as other methods of allowing Players to find and join online games. It includes Session Management, finding Sessions though search or other means, as well as joining and leaving those Sessions. Session Interface is created and owned by the Online Subsystem, this means it only exists on the Server, only one Session Interface will ever exist at a time - the Session Interface for the platform the engine is currently running on.

While the Session Interface performs all of the Session handling, the Game doesn't generally interact directly with it. Instead, the GameSession, AGameSession, acts as a game-specific wrapper around the Session Interface and the game code makes calls to it when it needs to interact with the Session. GameSession is created and owned by the GameMode, and also only exists on the Server when running an online game, each game can potentially have multiple GameSession types, but only one will ever be used at a time. Most common case for a game having more than one type of GameSession is to add a type of GameSession for when the game is using a Dedicated Server.

Session Settings

SessionSettings, defined by the FOnlineSessionSettingsclass, are a set of properties that determine the characteristics of the session. In the base implementation, these are things like;

• Number of Players allowed • Is the Session advertised or private • Is the Session a LAN match • Is the Server dedicated or Player-hosted • Are invites allowed • Etc.

Using the Online Game Lobby Example, each of those games is a Session and has its own SessionSettings. For example, some Sessions may be Player versus Player (PvP) while others are Cooperative Multiplayer (Co-Op). Different Sessions could be playing different maps or playlists, require different numbers of players, etc.

Session Management

All Session Nodes are Asynchronous tasks (Clock Symbol) and will call “OnSuccess” or “OnFailure” once they're finished. In the meanwhile, you can use the top most exec output.

Creating Sessions

In order for Players to find a Session and potentially join it, you need to create a Session and set up its properties, as well as decide which of those properties will be visible. Registering a Dedicated Server Session via Blueprint might not be supported at the current Engine Version. In C++ you should do the normal C++ Session creation inside the AGameSession by overriding the RegisterServer function.

For creating a Session in Blueprints, you can use the 'CreateSession' Node that Epic already exposed. It doesn't offer many options, but this can be extended via Plugins from the Forum.

Updating Session

Updating is done when you want to change the Settings of an existing Session and is performed using the IOnlineSession::UpdateSession() function. For example, the Session may be set up currently to only allow 8 Players, while it needs to allow 12 Players for the next match. To update the Session, UpdateSession() would be be called passing it new Session Settings that specify a 12 Player maximum. When the request to update a Session has completed, the OnUpdateSessionComplete delegate is fired.

Provides the opportunity to perform any configuration or initialization necessary to handle the Session Settings changing. Updating a Session is generally performed between Matches on the Server, but it is also performed on the Client in order to keep the Session information in sync. As of right now there is no Blueprint Version of this function yet, but it can be extended via Plugins from the Forum.

Destroying Session

When a Session ends and is no longer needed, the Session is destroyed using the IOnlineSession::DestroySession() function. When the destruction operation has completed, the OnDestroySessionComplete Delegate is fired, enabling you to perform cleanup operations.

Searching Sessions

Simplest way to find Sessions is to search for Sessions that match some desired subset of Settings, this could be in response to the Player choosing a collecting of filters in a User Interface. It could be done automatically behind the scenes, based on the Player's skill and other factors, or it could be a combination of both methods. Most basic form of Searching for Sessions is the classic Server Browser that shows all available games and allows the Player to filter those based on the type of Game they want to play.

Joining Sessions

Once you have determined a Session for the Player to join, the process of joining is initiated by calling IOnlineSession::JoinSession() and passing it the Number of the Player and the Name and SearchResult of the Session to join. When the joining process completes, the OnJoinSessionComplete Delegate is fired. This is where the logic to get the Player into the Match is performed.

For joining a Session via Blueprint, you can use the 'JoinSession' Node, that Epic already exposed. It needs a SessionResult, which you can get from the 'FindSession' Node. It returns on Array of SessionResults. The 'JoinSession' Node will directly join the Map 'OnSuccess'. You don't have to deal with that.

Concluding

Extensive guidance on using C++ Sessions in Unreal Engine.

Cloud Based Matchmaking

Cloud-Based Matchmaking refers to built-in Matchmaking Services that are available, and generally platform specific. An example of this type of service is the TrueSkill System available through the Microsoft Xbox Live Service. Initiate Matchmaking on Platforms that support it, you call IOnlineSession::Startmatchmaking() and pass it the Controller Number of the Player to matchmake for, the SessionName, SessionSettings to use if creating a new Session, and Settings to Search against.

OnMatchmakingComplete Delegate is fired when Matchmaking is complete, this provides a bool specifying whether the process was successful and the Name of the Session to join in that case. A Matchmaking action in process can be canceled by calling IOnlineSession::CancelMatchmaking() and passing it the Controller Number of the Player and the SessionName that was passed to the call to start Matchmaking in the first place, the OnCancelMatchmakingCompletedelegate is fired when the cancel operation is completed.

Following and Inviting Friends

On platforms that support the concept of Friends, Players can follow Friends into a Session or invite Friends to join them in a Session. Following a Friend into a Session is done by calling IOnlineSession:FindFriendSession() and passing it the Number of the local Player that wants to join the Session and the ID of the Friend already in the Session. OnFindFriendSessionComplete Delegate is fired when the Session is found and it contains a SearchResult that can be used to join the Session.

A Player can also invite one or more Friends to join them in their current Session using IOnlineSession::SendSessionInviteToFriend() or IOnlineSession::SendSessionInviteToFriends() and passing in the Local Player Number, SessionName, and ID(s) of the Player(s) to be invited. When a Friend accepts an invitation, the 'OnSessionInviteAccepted' Delegate containing the SearchResult of the Session to join is fired.