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

クイックプレイメニューを追加する - ピアツーピアでのクイックマッチ - (Unreal Engine モジュール)

Last updated on February 4, 2026

注釈:本資料はAI技術を用いて翻訳されています。

クイックプレイUIについて

Byte Warsでは、クイックプレイはマッチメイキング機能にアクセスする場所で、プレイヤーがゲームモードとサーバータイプを選択してマッチメイキングを行います。Byte Warsプロジェクトでは、クイックプレイはマッチメイキングを使用してゲームをプレイするためのウィジェットです。このウィジェットには、選択できる2種類のゲームモードがあります:EliminationTeam Deathmatchです。Eliminationは4人のフリーフォーオール(FFA)で、Team Deathmatchは2人ずつの2つの対戦チームで構成されます。

クイックプレイウィジェットはリソースセクションで利用可能で、以下のファイルで構成されています:

  • ヘッダーファイル: /Source/AccelByteWars/TutorialModules/Play/MatchmakingEssentials/UI/QuickPlayWidget.h
  • CPPファイル: /Source/AccelByteWars/TutorialModules/Play/MatchmakingEssentials/UI/QuickPlayWidget.cpp
  • Blueprintウィジェット: /Content/TutorialModules/Play/MatchmakingEssentials/UI/W_QuickPlay.uasset

このウィジェットには、マッチメイキングの状態に基づいて関連するユーザーインターフェース(UI)を表示するための異なる状態があります。状態は以下の通りです:

  • Select Game Mode: ゲームモードを選択するボタンを表示します。
  • Select Server Type: マッチメイキングに使用するサーバータイプを選択するボタンを表示します。ここでマッチメイキングピアツーピア(P2P)ボタンが生成されます。

このウィジェットで注目すべき重要な点は、選択されたゲームモードにアクセスする方法です。

EGameModeType UQuickPlayWidget::GetSelectedGameModeType() const
{
return SelectedGameModeType;
}
EGameStyle UQuickPlayWidget::GetSelectedGameStyle() const
{
return SelectedGameStyle;
}

マッチメイキングP2P UIについて

マッチメイキングP2P UIメニューは、実際のマッチメイキングフローが表示される場所です。関連ファイルはリソースセクションで利用可能で、以下のファイルで構成されています:

  • ヘッダーファイル: /Source/AccelByteWars/TutorialModules/Play/MatchmakingP2P/UI/MatchmakingP2PWidget_Starter.h
  • CPPファイル: /Source/AccelByteWars/TutorialModules/Play/MatchmakingP2P/UI/MatchmakingP2PWidget_Starter.cpp
  • Blueprintウィジェット: /Content/TutorialModules/Play/MatchmakingP2P/UI/W_MatchmakingP2P.uasset

このウィジェットにはすでにいくつかの機能が提供されているため、統合に集中できます。

  • OnlineSession変数。セッション機能へのゲートウェイです。
private:
UPROPERTY()
UAccelByteWarsOnlineSessionBase* OnlineSession;
void UMatchmakingP2PWidget_Starter::NativeOnActivated()
{
// ...
UOnlineSession* BaseOnlineSession = GetWorld()->GetGameInstance()->GetOnlineSession();
if (!ensure(BaseOnlineSession))
{
return;
}

OnlineSession = Cast<UAccelByteWarsOnlineSessionBase>(BaseOnlineSession);
ensure(OnlineSession);
// ...
}
  • SessionInvite変数。マッチの現在のセッション招待を保存します。
private:
// ...
TSharedPtr<FOnlineSessionInviteAccelByte> SessionInvite;
  • SelectedGameModeType変数。選択されたゲームモードタイプを保存します。クイックプレイUIから取得されます。
private:
// ...
EGameModeType SelectedGameModeType;
void UMatchmakingP2PWidget_Starter::NativeOnActivated()
{
// ...
UAccelByteWarsBaseUI* BaseUIWidget = Cast<UAccelByteWarsGameInstance>(GetGameInstance())->GetBaseUIWidget();
for (const UCommonActivatableWidget* Widget : BaseUIWidget->Stacks[EBaseUIStackType::Menu]->GetWidgetList())
{
if (const UQuickPlayWidget* QuickPlayWidget = Cast<UQuickPlayWidget>(Widget))
{
SelectedGameModeType = QuickPlayWidget->GetSelectedGameModeType();
SelectedGameStyle = QuickPlayWidget->GetSelectedGameStyle();
}
}
// ...
}
  • 各マッチメイキング状態を表すハイレベル状態:

    • Request Sent: リクエストが送信され、現在レスポンスを待っていることを示すローディング画面。
    • Finding Match: マッチを見つけるために現在待機中であることを示すキャンセルボタン付きのローディング画面。
    • Match Found: マッチが見つかり、次のステップに進もうとしていることを示すローディング画面。
    • Canceling Match: マッチキャンセルリクエストが送信され、現在レスポンスを待っていることを示すローディング画面。
    • Waiting for Player: プレイヤーが見つかったマッチに参加または拒否できる画面。
    • Rejecting Match: マッチ拒否リクエストが送信され、現在レスポンスを待っていることを示すローディング画面。
    • Joining Match: セッション参加リクエストが送信され、現在レスポンスを待っていることを示すローディング画面。
    • Session Joined: セッション参加成功レスポンスが受信され、次のステップに進もうとしていることを示すローディング画面。
    • Requesting Server: サーバーがリクエストされ、現在サーバーの準備を待っていることを示すローディング画面。
    • Error: リトライボタン付きの一般的なエラー画面。
  • これらのハイレベル状態を切り替える関数。マッチメイキングP2P UIには以下の関数があります:

// ...
protected:
// ...
void ChangeWidgetState(const EWidgetState State);
  • ハイレベル状態を表す実際の個別のウィジェットコンポーネントであるローレベル状態:
    • Loading: テキスト、サブテキスト、キャンセルボタンを含む、タスクが進行中であることを示す画面。

    • Error: エラーテキストとリトライボタンを含む、タスクが失敗したことを示す画面。

    • Waiting for Player: カウントダウンテキスト、参加ボタン、拒否ボタンを含む画面。

      状態変更は、3つのウィジェットコンポーネントを持つUnreal Motion GraphicsのWidget Switcherを使用して可能です。これらのコンポーネントの宣言は以下の通りです:

// ...
private:
// ...
UPROPERTY(BlueprintReadOnly, meta = (BindWidget, BlueprintProtected = true, AllowPrivateAccess = true))
UWidgetSwitcher* Ws_Root;

UPROPERTY(BlueprintReadOnly, meta = (BindWidget, BlueprintProtected = true, AllowPrivateAccess = true))
UWidget* W_Loading;

UPROPERTY(BlueprintReadOnly, meta = (BindWidget, BlueprintProtected = true, AllowPrivateAccess = true))
UWidget* W_Error;

UPROPERTY(BlueprintReadOnly, meta = (BindWidget, BlueprintProtected = true, AllowPrivateAccess = true))
UWidget* W_WaitingForPlayer;

Loading状態

ここでは、プレイヤーはテキスト、サブテキスト(ハイレベル状態に応じて)、およびハイレベル状態に応じて無効化される可能性のあるキャンセルボタンを見ることができます。

Loading状態のプレビュー

これらのコンポーネントはヘッダーファイルで宣言されています:

// ...
private:
// ...
UPROPERTY(BlueprintReadOnly, meta = (BindWidget, BlueprintProtected = true, AllowPrivateAccess = true))
UCommonButtonBase* Btn_Cancel;
// ...
UPROPERTY(BlueprintReadOnly, meta = (BindWidget, BlueprintProtected = true, AllowPrivateAccess = true))
UTextBlock* Tb_LoadingText;

UPROPERTY(BlueprintReadOnly, meta = (BindWidget, BlueprintProtected = true, AllowPrivateAccess = true))
UTextBlock* Tb_LoadingSubText;

Error状態

この状態では、プレイヤーはエラーテキスト、リトライボタン、戻るボタンを見ることができます。

Error状態のプレビュー

これらのコンポーネントはヘッダーファイルで宣言されています:

// ...
private:
// ...
UPROPERTY(BlueprintReadOnly, meta = (BindWidget, BlueprintProtected = true, AllowPrivateAccess = true))
UCommonButtonBase* Btn_Back;
// ...
UPROPERTY(BlueprintReadOnly, meta = (BindWidget, BlueprintProtected = true, AllowPrivateAccess = true))
UCommonButtonBase* Btn_Retry;
// ...
UPROPERTY(BlueprintReadOnly, meta = (BindWidget, BlueprintProtected = true, AllowPrivateAccess = true))
UTextBlock* Tb_ErrorText;

Waiting for Player状態

この状態は、プレイヤーがマッチに参加するか拒否するかを選択できる場所です。カウントダウン、参加ボタン、拒否ボタンで構成されています。

Waiting for Player状態のプレビュー

// ...
private:
// ...
UPROPERTY(BlueprintReadOnly, meta = (BindWidget, BlueprintProtected = true, AllowPrivateAccess = true))
UCommonButtonBase* Btn_Reject;

UPROPERTY(BlueprintReadOnly, meta = (BindWidget, BlueprintProtected = true, AllowPrivateAccess = true))
UCommonButtonBase* Btn_Join;
// ...
UPROPERTY(BlueprintReadOnly, meta = (BindWidget, BlueprintProtected = true, AllowPrivateAccess = true))
UTextBlock* Tb_WaitingForPlayersCountdown;

カウントダウンは自動参加機能として使用されます。カウントダウンがゼロになったときにプレイヤーが何もクリックしていない場合、後で定義するアクションがアクティブになります。以下は、ヘッダーファイルでのカウントダウン変数の宣言とCPPファイルでの実装です:

// ...
private:
// ...
const float AutoJoinDelay = 10;
// ...
float AutoJoinCurrentCountdown = 0;

UIの準備

このセクションでは、MatchmakingP2PWidget_Starterウィジェットクラスを準備して、クイックプレイウィジェットに表示されるようにします。

  1. マッチメイキングイベントをトリガーするために呼び出される関数を宣言します。MatchmakingP2PWidget_Starterヘッダーファイルを開き、以下のコードを追加します:

    protected:
    UFUNCTION()
    void StartMatchmaking();

    UFUNCTION()
    void JoinSession();

    UFUNCTION()
    void CancelMatchmaking();

    UFUNCTION()
    void RejectSessionInvite();
  2. MatchmakingP2PWidget_Starter CPPファイルを開き、StartMatchmaking()関数を定義します。後でこの関数はマッチメイキングをトリガーしますが、今のところは以下のダミー関数を追加します。W_Parent変数は親ウィジェット(クイックプレイウィジェット)への参照です。これにより、クイックプレイの状態を切り替えることができます。

    void UMatchmakingP2PWidget_Starter::StartMatchmaking()
    {
    if (OnlineSession->ValidateToStartMatchmaking.IsBound() &&
    !OnlineSession->ValidateToStartMatchmaking.Execute(SelectedGameModeType))
    {
    return;
    }

    // Reset stored invite
    SessionInvite = nullptr;

    // Reset auto join session countdown.
    AutoJoinCurrentCountdown = AutoJoinDelay;
    MatchFoundCurrentCountdown = MatchFoundDelay;
    SessionJoinedCurrentCountdown = SessionJoinedDelay;
    Tb_WaitingForPlayersCountdown->SetText(FText::FromString(FString::FromInt(AutoJoinCurrentCountdown)));

    ChangeWidgetState(EWidgetState::REQUEST_SENT);
    // ...
    }
  3. CancelMatchmaking()関数を定義します。後でこの関数はマッチメイキングをキャンセルするためにトリガーされますが、今のところは以下のダミー関数を追加します:

    void UMatchmakingP2PWidget_Starter::CancelMatchmaking()
    {
    ChangeWidgetState(EWidgetState::CANCELING_MATCH);
    // ...
    }
  4. MatchmakingP2PWidget_Starterヘッダーファイルに戻ります。マッチメイキングイベントが完了したときのコールバックを処理する以下の関数を宣言します。

    protected:
    // ...
    void OnStartMatchmakingComplete(FName SessionName, bool bSucceeded);
    void OnMatchmakingComplete(FName SessionName, bool bSucceeded);
    void OnSessionInviteReceived(
    const FUniqueNetId& UserId,
    const FUniqueNetId& FromId,
    const FOnlineSessionInviteAccelByte& Invite);
    void OnJoinSessionComplete(FName SessionName, EOnJoinSessionCompleteResult::Type Result);
    void OnSessionServerUpdateReceived(
    const FName SessionName,
    const FOnlineError& Error,
    const bool bHasClientTravelTriggered);

    void OnCancelMatchmakingComplete(FName SessionName, bool bSucceeded);
    void OnRejectSessionInviteComplete(bool bSucceeded);
  5. MatchmakingP2PWidget_Starter CPPファイルを開き、OnStartMatchmakingComplete()関数を定義します。この関数は、マッチメイキング開始プロセスが完了したときのコールバックを処理し、クイックプレイウィジェットを関連する状態に切り替えます。OnlineSession変数は、現在アクティブなオンラインセッションへの参照です。オンラインセッションの詳細については後で説明します。

    void UMatchmakingP2PWidget_Starter::OnStartMatchmakingComplete(FName SessionName, bool bSucceeded)
    {
    // Abort if not a game session.
    if (!SessionName.IsEqual(OnlineSession->GetPredefinedSessionNameFromType(EAccelByteV2SessionType::GameSession)))
    {
    return;
    }

    if (bSucceeded)
    {
    ChangeWidgetState(EWidgetState::FINDING_MATCH);
    }
    else
    {
    Tb_ErrorText->SetText(TEXT_FAILED_FIND_MATCH);
    ChangeWidgetState(EWidgetState::ERROR);
    }
    }
  6. OnMatchmakingComplete()関数を定義します。この関数は、マッチメイキングプロセスが完了したときのコールバックを処理し、クイックプレイウィジェットを関連する状態に切り替えます。

    void UMatchmakingP2PWidget_Starter::OnMatchmakingComplete(FName SessionName, bool bSucceeded)
    {
    // Abort if not a game session.
    if (!SessionName.IsEqual(OnlineSession->GetPredefinedSessionNameFromType(EAccelByteV2SessionType::GameSession)))
    {
    return;
    }

    if (bSucceeded)
    {
    ChangeWidgetState(EWidgetState::MATCH_FOUND);
    }
    else
    {
    Tb_ErrorText->SetText(TEXT_FAILED_FIND_MATCH);
    ChangeWidgetState(EWidgetState::ERROR);
    }
    }
  7. OnCancelMatchmakingComplete()関数を定義します。この関数は、マッチメイキングキャンセルプロセスが完了したときのコールバックを処理し、クイックプレイウィジェットを関連する状態に切り替えます。

    void UMatchmakingP2PWidget_Starter::OnCancelMatchmakingComplete(FName SessionName, bool bSucceeded)
    {
    // Abort if not a game session.
    if (!SessionName.IsEqual(OnlineSession->GetPredefinedSessionNameFromType(EAccelByteV2SessionType::GameSession)))
    {
    return;
    }

    // Abort if match already found.
    if (WidgetState == EWidgetState::MATCH_FOUND || WidgetState == EWidgetState::WAITING_FOR_PLAYER)
    {
    UE_LOG_MATCHMAKINGP2P(Log, TEXT("Match already found, cancel matchmaking canceled."))
    return;
    }

    if (bSucceeded)
    {
    DeactivateWidget();
    }
    else
    {
    Tb_ErrorText->SetText(TEXT_FAILED_CANCEL_MATCH);
    ChangeWidgetState(EWidgetState::ERROR);
    }
    }
  8. OnJoinSessionComplete()関数を定義します。この関数は、ゲームセッション参加プロセスが完了したときのコールバックを処理し、クイックプレイウィジェットを関連する状態に切り替えます。

    void UMatchmakingP2PWidget_Starter::OnJoinSessionComplete(FName SessionName, EOnJoinSessionCompleteResult::Type Result)
    {
    // Abort if not a game session.
    if (!SessionName.IsEqual(OnlineSession->GetPredefinedSessionNameFromType(EAccelByteV2SessionType::GameSession)))
    {
    return;
    }

    if(Result == EOnJoinSessionCompleteResult::Success)
    {
    ChangeWidgetState(EWidgetState::SESSION_JOINED);
    }
    else
    {
    Tb_ErrorText->SetText(TEXT_FAILED_JOIN_MATCH);
    ChangeWidgetState(EWidgetState::ERROR);
    }
    }
  9. OnCancelJoinSessionComplete()関数を定義します。この関数は、ゲームセッション参加プロセスがキャンセルされたときのコールバックを処理し、クイックプレイウィジェットを関連する状態に切り替えます。

    void UMatchmakingP2PWidget_Starter::OnCancelJoinSessionComplete(FName SessionName, bool bSucceeded) const
    {
    // Abort if not a game session.
    if (!SessionName.IsEqual(OnlineSession->GetPredefinedSessionNameFromType(EAccelByteV2SessionType::GameSession)))
    {
    return;
    }

    if (bSucceeded)
    {
    W_Parent->SwitchContent(UQuickPlayWidget::EContentType::SELECTGAMEMODE);
    }
    else
    {
    W_Parent->SetErrorMessage(TEXT_FAILED_CANCEL_MATCH, false);
    W_Parent->SwitchContent(UQuickPlayWidget::EContentType::ERROR);
    }
    }
  10. ボタンをバインドしてマッチメイキングを開始し、ウィジェットが開いたらすぐにマッチメイキング開始関数を呼び出します。NativeOnActivated()関数に以下のコードを追加します。

    void UMatchmakingP2PWidget_Starter::NativeOnActivated()
    {
    // ...
    Btn_Back->OnClicked().AddUObject(this, &ThisClass::DeactivateWidget);
    Btn_Join->OnClicked().AddUObject(this, &ThisClass::JoinSession);
    Btn_Cancel->OnClicked().AddUObject(this, &ThisClass::CancelMatchmaking);
    Btn_Reject->OnClicked().AddUObject(this, &ThisClass::RejectSessionInvite);
    Btn_Retry->OnClicked().AddUObject(this, &ThisClass::StartMatchmaking);
    // ...
    StartMatchmaking();
    }
  11. ウィジェットがアクティブでないときにこれらのボタンのバインドを解除します。NativeOnDeactivated()に以下のコードを追加します:

    void UMatchmakingP2PWidget_Starter::NativeOnDeactivated()
    {
    Btn_Back->OnClicked().RemoveAll(this);
    Btn_Join->OnClicked().RemoveAll(this);
    Btn_Cancel->OnClicked().RemoveAll(this);
    Btn_Reject->OnClicked().RemoveAll(this);
    Btn_Retry->OnClicked().RemoveAll(this);
    // ...
    Super::NativeOnDeactivated();
    }
  12. プロジェクトをビルドし、Unreal Engine Editorで開きます。Editorで/Content/TutorialModules/Play/MatchmakingP2P/に移動します。そこにDA_MatchmakingP2PEssentialsというデータアセットがあります。それを開き、Is Starter Mode Activeを有効にします。次に、データアセットを保存します。これにより、ゲームをプレイするときにウィジェットをナビゲートできるようになります。

    Activate tutorial module data asset starter mode Unreal Byte Wars quick match peer-to-peer

  13. Editorでゲームをプレイします。メインメニューからPlay Online > Quick Play > Elimination > P2Pに移動します。実装が成功していれば、ローディング状態が表示され、キャンセルしてサーバー選択状態に戻ることができます。

リソース