メインコンテンツまでスキップ

セッション作成メニューを追加する - セッション入門 - (Unreal Engine モジュール)

Last updated on October 23, 2024

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
  • 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
備考

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;

Preview of the Default state unreal engine session essentials

Loading state

The Loading state is provided by Ws_Processing, the custom Widget Switcher. This state is only comprised of a loading message.

Preview of the Loading state unreal engine session essentials

Error state

The Error state is also provided by Ws_Processing, which consists of an error message and a retry button.

Preview of the Error state unreal engine session essentials

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;

Preview of Success state

Ready the UI

In this section, you will prepare the UI for AccelByte Gaming Services (AGS) Session integration.

  1. 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);
  2. 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);
    }
    }
  3. 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);
  4. 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);
    }
    }
  5. Bind the functions to the corresponding buttons by adding the code below to NativeOnActivated inside the CreateSessionWidget_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
    // ...
    }
  6. 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
    // ...
    }
  7. Build Byte Wars in Visual Studio and open it in the Unreal Editor.

  8. From the Unreal Editor Content Browser, navigate to /Content/TutorialModules/Play/SessionEssentials/UI/ and open W_CreateSession_Starter. Make sure that all widgets are bound properly in the Bind Widgets tab and the Parent class is set to CreateSessionWidget_Starter.

    Bind widgets tab Unreal Engine session essentials

  9. Test the session creation widget by opening Content/TutorialModules/Play/SessionEssentials/DA_SessionEssentials.uasset and enabling the Is Starter Mode Active. Save the Data Asset.

    Data Asset changes preview Unreal Engine session essentials

  10. Play the game in the editor, navigate to Online Play > Create a Session, and the starter UI will be shown if implemented correctly.

Resources