Add session creation menu - Introduction to Session - (Unreal Engine module)
What's on the menu
In this tutorial, you will learn how to prepare a session creation user interface (UI) menu that you will use to send session creation and leave requests. The files have been provided for you in the Resources section and consists of two parts:
CreateSessionWidget_Starter
: A C++ class that will hold most of the implementation.- Header file:
/Source/AccelByteWars/TutorialModules/Play/SessionEssentials/UI/CreateSessionWidget_Starter.h
- CPP file:
/Source/AccelByteWars/TutorialModules/Play/SessionEssentials/UI/CreateSessionWidget_Starter.cpp
- Header file:
W_CreateSession_Starter
: A widget Blueprint class that was created and designed using Unreal Motion Graphics (UMG).- Widget Blueprint file:
/Content/TutorialModules/Play/UI/W_CreateSession_Starter.uasset
- Widget Blueprint file:
For more detailed information about UMG, read UMG UI Designer.
The session creation menu has four states:
- Default: showing a Create Session button.
- Loading: showing a request was sent and is waiting for the response.
- Error: showing an error message if the request failed or an error response was received.
- Success: showing the created session's ID and a Leave button.
The state changes are possible using a combination between Widget Switcher, a component that's provided by the engine, and AccelByteWars Widget Switcher
, a custom Widget Switcher with predefined child widgets to show empty, loading, error, and successful states.
For more detailed info about Widget Switcher, read Unreal Engine API Reference.
Here is the declaration of those widgets in the C++ header file:
private:
// ...
UPROPERTY(BlueprintReadOnly, meta = (BindWidget, BlueprintProtected = true, AllowPrivateAccess = true))
UWidgetSwitcher* Ws_ContentOuter;
UPROPERTY(BlueprintReadOnly, meta = (BindWidget, BlueprintProtected = true, AllowPrivateAccess = true))
UWidget* W_Selection;
UPROPERTY(BlueprintReadOnly, meta = (BindWidget, BlueprintProtected = true, AllowPrivateAccess = true))
UAccelByteWarsWidgetSwitcher* Ws_Processing;
The utility function to change the state of those widgets has been provided. This function will handle switching the Widget Switcher's child and controller's focus.
void UCreateSessionWidget_Starter::SwitchContent(const EContentType Type)
{
UWidget* ContentTarget = nullptr;
UWidget* FocusTarget = nullptr;
EAccelByteWarsWidgetSwitcherState ProcessingWidgetState = EAccelByteWarsWidgetSwitcherState::Empty;
bool bEnableBackButton = true;
switch (Type)
{
case EContentType::CREATE:
ContentTarget = W_Selection;
FocusTarget = Btn_CreateSession;
break;
case EContentType::LOADING:
ContentTarget = Ws_Processing;
ProcessingWidgetState = EAccelByteWarsWidgetSwitcherState::Loading;
bEnableBackButton = false;
break;
case EContentType::SUCCESS:
ContentTarget = Ws_Processing;
ProcessingWidgetState = EAccelByteWarsWidgetSwitcherState::Not_Empty;
FocusTarget = Btn_Leave;
break;
case EContentType::ERROR:
ContentTarget = Ws_Processing;
ProcessingWidgetState = EAccelByteWarsWidgetSwitcherState::Error;
FocusTarget = Btn_Back;
break;
default: ;
}
if (FocusTarget)
{
DesiredFocusTargetButton = FocusTarget;
FocusTarget->SetUserFocus(GetOwningPlayer());
}
Ws_ContentOuter->SetActiveWidget(ContentTarget);
if (ProcessingWidgetState != EAccelByteWarsWidgetSwitcherState::Empty)
{
Ws_Processing->SetWidgetState(ProcessingWidgetState);
}
Btn_Back->SetIsEnabled(bEnableBackButton);
bIsBackHandler = bEnableBackButton;
RequestRefreshFocus();
// Set FTUEs
if (Type == EContentType::SUCCESS)
{
InitializeFTUEDialogues(true);
}
else
{
DeinitializeFTUEDialogues();
}
}
Default state
The Default state displays a button called Btn_CreateSession
and is bound to its C++ parent class.
It uses Common Button Base as the button type.
The code below is the button declaration in the class Header file.
private:
// ...
UPROPERTY(BlueprintReadOnly, meta = (BindWidget, BlueprintProtected = true, AllowPrivateAccess = true))
UCommonButtonBase* Btn_CreateSession;
Loading state
The Loading state is provided by Ws_Processing
, the custom Widget Switcher. This state is only comprised of a loading message.
Error state
The Error state is also provided by Ws_Processing
, which consists of an error message and a retry button.
Success state
The Success state is comprised of a message for successful session creation, a text box called Tb_SessionId
to display the session ID, and a leave button called Btn_leave
.
Here is the declaration of the text box and the button:
private:
// ...
UPROPERTY(BlueprintReadOnly, meta = (BindWidget, BlueprintProtected = true, AllowPrivateAccess = true))
UCommonButtonBase* Btn_Leave;
// ...
UPROPERTY(BlueprintReadOnly, meta = (BindWidget, BlueprintProtected = true, AllowPrivateAccess = true))
UTextBlock* Tb_SessionId;
Ready the UI
In this section, you will prepare the UI for AccelByte Gaming Services (AGS) Session integration.
To implement session creation, open the
CreateSessionWidget_Starter
class Header file in Visual Studio and add the following code:protected:
// ...
UFUNCTION()
void CreateSession();
UFUNCTION()
void OnCreateSessionComplete(FName SessionName, bool bSucceeded);Open the
CreateSessionWidget_Starter
class CPP file and add the following code:void UCreateSessionWidget_Starter::CreateSession()
{
if (!SessionOnlineSession)
{
return;
}
// An event to validate to start the session will be used in the Play with Party module.
if (SessionOnlineSession->ValidateToStartSession.IsBound() &&
!SessionOnlineSession->ValidateToStartSession.Execute())
{
return;
}
Ws_Processing->LoadingMessage = TEXT_REQUESTING_SESSION_CREATION;
SwitchContent(EContentType::LOADING);
// ...
}void UCreateSessionWidget_Starter::OnCreateSessionComplete(FName SessionName, bool bSucceeded)
{
// Abort if not a game session.
if (!SessionName.IsEqual(SessionOnlineSession->GetPredefinedSessionNameFromType(EAccelByteV2SessionType::GameSession)))
{
return;
}
if (bSucceeded)
{
// Get session ID
const FNamedOnlineSession* OnlineSession = SessionOnlineSession->GetSession(SessionName);
Tb_SessionId->SetText(FText::FromString(OnlineSession->GetSessionIdStr()));
SwitchContent(EContentType::SUCCESS);
}
else
{
Ws_Processing->ErrorMessage = TEXT_FAILED_TO_CREATE_SESSION;
Ws_Processing->bShowRetryButtonOnError = true;
SwitchContent(EContentType::ERROR);
}
}To implement leaving sessions, open
CreateSessionWidget_Starter
class Header file and add the following code:protected:
// ...
UFUNCTION()
void LeaveSession();
UFUNCTION()
void OnLeaveSessionComplete(FName SessionName, bool bSucceeded);Open the
CreateSessionWidget_Starter
class CPP file and add the following code:void UCreateSessionWidget_Starter::LeaveSession()
{
if (!SessionOnlineSession)
{
return;
}
Ws_Processing->LoadingMessage = TEXT_LEAVING_SESSION;
SwitchContent(EContentType::LOADING);
// ...
}void UCreateSessionWidget_Starter::OnLeaveSessionComplete(FName SessionName, bool bSucceeded)
{
// Abort if not a game session.
if (!SessionName.IsEqual(SessionOnlineSession->GetPredefinedSessionNameFromType(EAccelByteV2SessionType::GameSession)))
{
return;
}
if (bSucceeded)
{
SwitchContent(EContentType::CREATE);
}
else
{
Ws_Processing->ErrorMessage = TEXT_FAILED_TO_LEAVE_SESSION;
Ws_Processing->bShowRetryButtonOnError = false;
SwitchContent(EContentType::ERROR);
}
}Bind the functions to the corresponding buttons by adding the code below to
NativeOnActivated
inside theCreateSessionWidget_Starter
class CPP file:void UCreateSessionWidget_Starter::NativeOnActivated()
{
Super::NativeOnActivated();
#pragma region "UI related"
Btn_Back->OnClicked().AddUObject(this, &ThisClass::DeactivateWidget);
Btn_CreateSession->OnClicked().AddUObject(this, &ThisClass::CreateSession);
Btn_Leave->OnClicked().AddUObject(this, &ThisClass::LeaveSession);
Ws_Processing->OnRetryClicked.AddUObject(this, &ThisClass::CreateSession);
#pragma endregion
// ...
}Unbind those functions when the widget closes by navigating to
NativeOnDeactivated
in the same CPP file and adding the code below:void UCreateSessionWidget_Starter::NativeOnDeactivated()
{
Super::NativeOnDeactivated();
#pragma region "UI related"
Btn_CreateSession->OnClicked().RemoveAll(this);
Btn_Back->OnClicked().RemoveAll(this);
Btn_Leave->OnClicked().RemoveAll(this);
Ws_Processing->OnRetryClicked.RemoveAll(this);
#pragma endregion
// ...
}Build Byte Wars in Visual Studio and open it in the Unreal Editor.
From the Unreal Editor Content Browser, navigate to
/Content/TutorialModules/Play/SessionEssentials/UI/
and openW_CreateSession_Starter
. Make sure that all widgets are bound properly in the Bind Widgets tab and the Parent class is set toCreateSessionWidget_Starter
.Test the session creation widget by opening
Content/TutorialModules/Play/SessionEssentials/DA_SessionEssentials.uasset
and enabling theIs Starter Mode Active
. Save the Data Asset.Play the game in the editor, navigate to Online Play > Create a Session, and the starter UI will be shown if implemented correctly.
Resources
- The files used in this tutorial section are available in the Byte Wars Unreal GitHub repository.
- AccelByteWars/Content/TutorialModules/Play/SessionEssentials/DA_SessionEssentials.uasset
- AccelByteWars/Content/TutorialModules/Play/SessionEssentials/UI/W_CreateSession_Starter.uasset
- AccelByteWars/Source/AccelByteWars/TutorialModules/Play/SessionEssentials/UI/CreateSessionWidget_Starter.h
- AccelByteWars/Source/AccelByteWars/TutorialModules/Play/SessionEssentials/UI/CreateSessionWidget_Starter.cpp