X157 Dev Notes

One simulant attempts to share insight with others.

Lyra Experience

A Lyra Experience is a custom, configurable Game Mode/State. Each level in a Lyra project can specify the Default Lyra Experience to load for that level via custom World Settings.

Loading a Lyra Experience is asynchronous. Content is expected to be placed into Game Feature Plugins (GFPs) which are dynamically loaded only when actually needed. Your project is expected to use the On Experience Loaded event to initiate gameplay, it fires when the async loading completes.

The Experience Definition configures the default Lyra Pawn Data and a list of Experience Action Sets to load and execute. (Runtime component injection, HUD widget extension, etc.)

Note that BeginPlay has a different meaning in Lyra. Whereas in other games Begin Play might literally mean in some cases “game play has begun”, in Lyra it just means the Level has been loaded and the (perhaps quite slow) async loading process has begun. In Lyra, the game shouldn’t actually start playing until the On Experience Loaded event fires, sometime well after BeginPlay.

You can test delayed Experience loading (e.g. to simulate slow computers/networks) by setting some console variables.

Primary Data Assets Defining an Experience

Unreal Engine Setup

How to Initiate Gameplay in a Lyra Experience

Debugging Tips

Execute these console commands to enable Verbose logging for these modules:

Execute ModularGameplay.DumpGameFrameworkComponentManagers in the console to dump debugging info to help understand which components are being injected into which actors.

See Console Variables, they are helpful for debugging.

Primary Data Assets

This section describes the major Primary Data Assets that are required to define a Lyra Experience.

Lyra Experience Definition

« Primary Data Asset »

This is a Const Data Asset. It literally defines a given Experience.

Lyra Experience Action Set

« Primary Data Asset »

Lyra Pawn Data

« Primary Data Asset »

Lyra Input Config

« Const Data Asset »

Game Feature Action

An Action to be taken when a Game Feature is activated. Part of the experimental GameFeatures plugin.

An Instanced Game Feature Action handles Game Features asset loading and unloading. Events include:

Setting up Unreal Engine for Lyra Experience

This section describes how Lyra sets up Unreal Engine to support a Lyra Experience.

Lyra Game Mode

Lyra Game Mode is the required base Game Mode providing Lyra Experience support.

Initialization of the Game Mode is discussed separately.

Lyra Game State

The Lyra Game State is key to the functionality of Lyra Experiences.

The Lyra Game State itself is relatively simple, but it does initialize and activate two very important components that enable Experiences:

Lyra Experience Manager Component

The ULyraExperienceManagerComponent does the heavy lifting related to loading and unloading, activating and deactivating Experiences.

Experience Loading Procedure: StartExperienceLoad

On the server and on all clients, StartExperienceLoad must be called (explicitly on the server and via replication on the clients), which begins this process:

State: Loading
State: Loading Game Features
State: Executing Actions
State: Loaded

Lyra World Settings

Config/DefaultEngine.ini configures the use of Lyra World Settings:

[/Script/Engine.Engine]
WorldSettingsClassName=/Script/LyraGame.LyraWorldSettings

Lyra Asset Manager

Config/DefaultEngine.ini configures the use of Lyra Asset Manager:

[/Script/Engine.Engine]
AssetManagerClassName=/Script/LyraGame.LyraAssetManager

Lyra Experience Manager

« Engine Subsystem »

Console Variables

For testing purposes, you can add a delay to the Lyra Experience Loading process to simulate slow computers and/or networks.

Lyra Gameplay Initiation

This section discusses the intended way to initiate actual gameplay in a Lyra Experience. TLDR do not use BeginPlay to start gameplay, instead in BeginPlay you need to wait for OnExperienceLoaded.

On Experience Loaded

The Lyra Experience Manager Component will broadcast the OnExperienceLoaded event after the asynchronous experience loading process has completed.

Your game needs to be diligent about using this event to initiate game play, and not use BeginPlay for that purpose. Using BeginPlay to initiate game play will result in intermittent errors.

Lyra also provides AsyncAction_OnExperienceLoaded which is an asynchronous BP action, so that you can easily wait for OnExperienceLoaded in BPs. Lyra does this when it initializes its Shooter Mannequin character, for example.

Three Levels of Priority

The OnExperienceLoaded event is fired with three different levels of priority to allow you to have some handlers that are dependent on other higher priority handlers.

The system is minimal. For complex interdependencies you will need to devise your own solution, and understand that the callbacks are executed in random order.

Examples of OnExperienceLoaded in C++ and BP

There are many examples of how to use OnExperienceLoaded in Lyra. CTRL+SHIFT+F in Rider to see many interesting C++ snippets. Some examples of particular interest are discussed below.

High Priority Examples

Normal Priority Examples

Low Priority Examples

Example BP Hooking into OnExperienceLoaded

Example BP Hook

Example C++ Hooking into OnExperienceLoaded

In this C++ example, you’d set BeginPlay as follows:

void AMyExampleActor::BeginPlay()
{
    Super::BeginPlay();

    // Boilerplate OnExperienceLoaded hook:
    // TODO consider moving this to a static helper class so you can paste 1 line instead of 5
    AGameStateBase* GameState = GetWorld()->GetGameState();
    check(GameState);
    ULyraExperienceManagerComponent* ExperienceComponent = GameState->FindComponentByClass<ULyraExperienceManagerComponent>();
    check(ExperienceComponent);
    ExperienceComponent->CallOrRegister_OnExperienceLoaded(FOnLyraExperienceLoaded::FDelegate::CreateUObject(this, &ThisClass::OnExperienceLoaded));
}

You must also create an OnExperienceLoaded handler in AMyExampleActor to receive the event:

// Called by Lyra Experience Manager
void AMyExampleActor::OnExperienceLoaded(const ULyraExperienceDefinition* Experience)
{
    DoStuff();
}

Loading a Default Experience

Lyra loads the Frontend Experience as the default by injecting the Lyra Frontend State Component into the Lyra Game State from a Lyra Experience Definition.

For example, the map Lyra uses by default to start the game is L_LyraFrontEnd, which uses B_LyraFrontEnd_Experience as the Default Gameplay Experience.

An AddComponents Game Feature Action in B_LyraFrontEnd_Experience injects B_LyraFrontendStateComponent into the LyraGameState, which causes the Lyra FrontEnd Experience to load on Game start.

Lyra Frontend State Component

The B_LyraFrontendStateComponent is a simple BP configuration of Lyra Frontend State Component, defining the menu widgets used by the project.

This component is expected to be injected into a Lyra Game State. It registers a high priority OnExperienceLoaded callback that initiates the asynchronous process of showing the frontend menu system to the user.

This interfaces with the CommonLoadingScreen plugin that is distributed with Lyra. That allows the loading screen to be visible for however long it takes to load the Lyra Experience.

Once the Experience has loaded and the player is ready to see the menu, the loading screen is disabled and the menu system is displayed.