Unreal SDK - Runtime Concepts¶
The Beamable SDK is a collection of custom UE Engine
, Editor
and GameInstance
Subsystems. Game-Maker Code (as in, code the Beamable customer writes) can take advantage of various guarantees we provide by understanding how these subsystems work.
UBeamUserSlots
and FUserSlot
¶
The concept of a UserSlot
represents a named "local player" slot. By default, we ship with two lists of User Slots inside the UBeamCoreSettings
(found in Project Settings -> Engine
) :
- The
RuntimeUserSlots
, that contains a default slot at index 0, calledPlayer0
.- The first index of this list is referred to as the
OwnerPlayerSlot
. - This list is the list of expected player slots for every running client of your game.
- If you're game does not need multiple users logged into the same game-client, you don't need multiple slots.
- The first index of this list is referred to as the
- The
EditorUserSlots
, that contains a default slot at index 0, calledMainEditorDeveloperSlot
.- The Beamable Editor integration also uses the user slot system to authenticate the requests it makes to the Beamable servers. So... when you signed into the editor, you're data is associated to this default slot.
The UBeamUserSlots
Engine Subsystem is responsible for:
- Enabling local co-op games to have multiple players logged in at the same time.
- Name-spacing slots to support Multiplayer PIE-mode.
- This is why, like UE, we take in a
UObject* CallingContext
in certain parts of our APIs.
- This is why, like UE, we take in a
- Assert that only slots defined in the
UBeamCoreSettings
are in use.- Any User Slot with
Test
in its name is exempt from this rule so you can write automated tests with arbitrary amounts of user slots by using user slots withTest
in their names.
- Any User Slot with
This subsystem does not handle the actual logging in and logging out. That is handled by two other Subsystems:
UBeamRuntime
, aGameInstanceSubsystem
, is responsible for PIE instances and packaged games.UBeamEditor
, anEditorSubsystem
, is responsible for the Editor integration.
UBeamRuntime
& UBeamRuntimeSubsystem
¶
UBeamRuntime
is the entry point for the Beamable SDK at runtime (PIE, packaged game clients and dedicated servers). It is a GameInstanceSubsystem
and follows its lifecycle rules. It is responsible for a couple of things:
- It controls the SDK's runtime initialization flow.
- It controls the various SDK's user [un]-authentication flows.
- It controls
UBeamRuntimeSubsystems'
lifecycle with respect to the SDK itself andFUserSlots
.
The image below describes how the SDK's lifecycle injects itself into UE's lifecycle:
The next image shows a high-level description of the authentication flows supported by the SDK:
Now that you have a high-level understanding of the SDK's initialization flows, read up on how to achieve the two most common Sign Up and Login flows among the ones we provide.
Player Sign Up and Login Flows with Beamable¶
The Beamable SDK comes with a set of pre-implemented operations for common sign-up use-cases. Here are how to set up a few of the common login/signup flows using Beamable.
Mobile and Console Support
We DO NOT provide mobile support yet. This version of the SDK is focused on PC (Windows/Linux) and Dedicated Servers. Console and Mobile support will be added later.
Login Flow - "Mobile Games" Style Authentication¶
Mobile games often want to create a Guest Account for the player so they can start playing quickly and later decide if they want to Attach
that guest account to a more permanent identity.
The SDK supports this flow via the UBeamRuntime::InitSDKWithFrictionlessLogin
function. Initializing the SDK with this function will immediately attempt to create a Guest Account at the OwnerPlayerSlot
as soon as the SDK finishes initializing itself. If an account is already locally cached at that FUserSlot
we'll login to that one automatically without making a request to Beamable.
The On User Ready
callback provided to the InitSDKWithFrictionlessLogin
function runs after the Guest Account was successfully created and, at that point, you can make further requests to Beamable.
Guest Accounts are lost if signed out (or have its locally cached data lost for any reason). To avoid that, players can to "attach" some persistent identity information to that guest account. UBeamRuntime::Attach_____
do that. After a successful attach call, a player will be able to login via the corresponding UBeamRuntime::Login____
operation. For example, if you AttachEmailAndPassword
you'll be able to LoginEmailAndPassword
to sign back into the account.
This user sign in flow does not run in Dedicated Servers even if InitSDKWithFrictionlessLogin
is called. Dedicated Servers use a different form of authentication that is not based on FUserSlots
.
Login Flow - "PC/Console" Style Authentication¶
In PC/Console titles, often the user can sign-in and up from inside the game. That can happen either through an active form-filling process, an active request to third-party authentication (Discord, Google, etc...) or an automatic store-based login (Epic Online Services, PSN, Steam, etc...).
If your game has these flows, we recommend you use InitSDK
and manage the login/signup flows in your game code instead. The steps below explain how to do that.
In your BeginPlay
implementation, call UBeamRuntime::InitSDK
. It provides you different callbacks to handle initialization success or failure. At the end of a successful initialization, you can call UBeamRuntime::SignUp____
or UBeamRuntime::Login____
Operations with the appropriate parameters to login a user.
You can react to the successful Login/SignUp either via registering a callback to UBeamRuntime::OnUserReady
OR by the operation's own events.
We treat these operations as atomic inside the SDK and will clear any invalid partial state in case of any failure during their internal multi-step process; triggering UBeamRuntime::OnUserReady
only in the case that the user is fully ready for use.
Understanding BeamRuntimeSubsystems
¶
BeamRuntimeSubsystems
are stateful subsystems that provide some specific Beamable functionality. They are built on top of our Auto Generated UBeam____Api
classses to make it simpler to leverage our APIs; that way:
- You don't have to set up the common case.
- You can use them and their extension points for variations of the common case.
- You can use them as reference implementations to implement your own custom use cases outside of the common case.
These are hand-written. Here's a few examples of existing ones:
UBeamContentSubsystem
: This leverages the Beamable Content system to receive dynamic updates to read-only game data definition; also supports baked in-build content through the same API.UBeamInventorySubsystem
: This provides builder functions around our Inventory APIs that allows you to combine what would be multiple API requests into a single batched inventory update. It also receives inventory notifications coming from the server and keeps those in sync.UBeamMatchmakingSubsystem
: This provides you a stateful way of joining/canceling a matchmaking queue and receiving updates when a match is found.
These systems make use of the various UBeamRuntime::____
callbacks to keep their state correct and expose callbacks and configuration options for Game-Maker Code to run with semantically relevant guarantees.
If the exposed hooks on these are not enough for your use case and constraints, as a user you can create your own UBeamRuntimeSubsystem
. The SDK tries not to hide things from you so you can use the provided UBeamRuntimeSubsystems
to understand how they are set up when creating your own. The documentation in [Lower-Level SDK Subsystems][#lower-level-sdk-subsystems] can also be useful when implementing your own UBeamRuntimeSubsystems
.
You can also opt out of these entirely by adding them to UBeamCoreSettings
's property: ManuallyInitializedRuntimeSubsystems
. All subsystems in this list, and any other subsystem that depends on it, are not automatically initialized by the SDK. For example: adding UBeamInventorySubsystem
to this list makes it so the SDK's default implementation of an inventory system will not be in-use until you manually initialize it.
You can leverage the above to:
- Delay initialization of subsystems to a later point to reduce startup times.
- Remove our implementation of a set of systems so that you can use your own implementation of those systems.
- Disable systems that you do not want to use to reduce the SDK's request overhead.
Keep in mind that the simplest way is to build your features on top of these subsystems instead of replacing them. However, there are complex cases where it may be easier to make your own system instead of these subsystems. That's why we allow you to enable/disable systems with this granularity.
Lower-Level SDK Subsystems¶
This section talks about lower-level details of how requests to Beamable get made. You don't need to read this, but... you might want to if you plan on implementing your own UBeamRuntimeSubsystem
. Here's why you'd want to do this:
- You want to replace one of our implementations with something quite custom and want to provide guarantees about your system's lifecycle that are similar to the ones we provide.
- You wish to guarantee that
On User Ready
has access to custom data fetched via Microservices and Microstorages.
We don't recommend writing your own unless you're confident you understand the topics below and are trying to solve one of the two problems listed above.
The lowest layer of systems are shared between the SDK's UE Editor integration and the SDK's Runtime integration:
-
UBeamUserSlots
: As explained at the start of this document, tracks multiple local signed-in users (for local co-op cases). -
UBeam_____Api
: Code-Generated Subsystems from our Backend OpenAPI spec.- These are stateless subsystems.
- These provides you low-level access to every end-point of our backend even if we don't have utilities in the SDK that do exactly what you want.
- As UE doesn't allow for namespaces AND BP-compatibility, this is verbose. We recommend more liberal use of
auto
when dealing with Code-Gen API Types.
-
UBeamBackend
: Contains BP-Compatible and Lambda compatible implementations of Request/Response handling functions. It handles:- Request/Response serialization and deserialization.
- Configurable Retry Logic. Request, User and call-site granularity.
- Transparent and Automatic Re-Auth in case of expired
AccessToken
through a user'sRefreshToken
. LogBeamBackend Verbose
also is a useful diagnostic tool as it will print out the entire process of building the request, sending it out and receiving its response.
-
UBeamNotifications
andUBeam_____Notifications
: Leverages UE's WebSocket implementation and associates different web-socket connections with different user slots.UBeam_____Notifications
are implemented per Beamable backend system (inventory, stats, etc...) to expose two UE function versions, one BP-Compatible and the other Lambda-Compatible, that register a handler to process a specific type of notification.- These are used by
UBeamRuntimeSubsystem
based on their semantic needs. For example,UBeamMatchmakingNotifications
subscribes to notifications for the matchmaking ticket while a UserSlot is on a given queue. - You can use Microservices to send out custom notifications --- those can be received in clients by creating your own subsystem modeled after these.
-
UBeamRequestTracker
: A BP-compatible implementation of Async Operations that can emit various Events as it goes along --- you can think of these as "BP-Compatible Promises".- These are integrated with our
UBeam____Api
subsystems. BeginOperation
is effectively the same a creating a new promise.TriggerOperationSuccess
,TriggerOperationError
andTriggerOperationCancelled
should be called when you want to complete the Operation.- This is a somewhat complex subsystem so we recommend you read Operations & Waits.
- These are integrated with our
The systems above are used by various environments the Beamable SDK runs in: PIE, Editor, Dedicated Server Builds and regular game builds. Their code is pretty heavily commented; so, feel free to read it and figure things out that way.
Docs: C++ version of Blueprint examples¶
Most of our docs contains examples using Blueprints. Unless described otherwise there is option to achieve same results in C++ while following Blueprint sample. In C++, the subsystems and function names are the same except that, for lambda-binding, you'll need to use the CPP_
versions of functions.