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

すべてをまとめる - セッションチャット - (Unreal Engine モジュール)

Last updated on February 4, 2026

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

UI をセッションチャットに接続する

このチュートリアルでは、SessionChatSubsystem_Starter での実装をセッションチャットウィジェットに接続します。

  1. SessionChatWidget_Starter CPP ファイルを開き、セッションチャットメッセージを送信するために UI を接続することから始めます。SendSessionChatMessage() コードを次のコードに置き換えます:

    void USessionChatWidget_Starter::SendChatMessage(const FText& MessageText)
    {
    if (!SessionChatSubsystem)
    {
    UE_LOG_SESSIONCHAT(Warning, TEXT("Cannot send chat message. Session Chat subsystem is not valid."));
    return;
    }

    if (!ensure(GetOwningPlayer()))
    {
    UE_LOG_SESSIONCHAT(Warning, TEXT("Cannot send chat message. PlayerController is not valid."));
    return;
    }

    const ULocalPlayer* LocalPlayer = GetOwningPlayer()->GetLocalPlayer();
    if (!ensure(LocalPlayer))
    {
    UE_LOG_SESSIONCHAT(Warning, TEXT("Cannot send chat message. LocalPlayer is not valid."));
    return;
    }

    // Send room chat message.
    SessionChatSubsystem->SendChatMessage(
    LocalPlayer->GetPreferredUniqueNetId().GetUniqueNetId(),
    SessionChatSubsystem->GetChatRoomIdBasedOnType(CurrentChatRoomType),
    MessageText.ToString());
    }
  2. 次に、OnSendChatComplete() 関数を以下のコードに置き換えて、現在のウィジェットチャットタイプに応じて送信されたチャットを表示するかどうかを確認します:

    void USessionChatWidget_Starter::OnSendChatComplete(FString UserId, FString MsgBody, FString RoomId, bool bWasSuccessful)
    {
    // Abort and push a notification if failed.
    if (!bWasSuccessful)
    {
    if (PromptSubsystem)
    {
    PromptSubsystem->PushNotification(SEND_CHAT_FAILED_MESSAGE);
    }

    return;
    }

    if (!SessionChatSubsystem)
    {
    UE_LOG_SESSIONCHAT(Warning, TEXT("Cannot display a sent chat message. Session Chat subsystem is not valid."));
    return;
    }

    // Only show the chat if the type is valid.
    if (SessionChatSubsystem->GetChatRoomType(RoomId) != CurrentChatRoomType)
    {
    return;
    }

    // Display the chat if success.
    UChatData* ChatData = NewObject<UChatData>();
    ChatData->Message = MsgBody;
    ChatData->bIsSenderLocal = true;
    W_ActiveChat->AppendChatMessage(ChatData);
    }
  3. OnChatRoomMessageReceived() 関数を以下のコードに置き換えて、表示されるチャットに追加する前に新しいチャットタイプを最初に確認します:

    void USessionChatWidget_Starter::OnChatRoomMessageReceived(const FUniqueNetId& UserId, const FChatRoomId& RoomId, const TSharedRef<FChatMessage>& Message)
    {
    if (!SessionChatSubsystem)
    {
    UE_LOG_SESSIONCHAT(Warning, TEXT("Cannot display a received chat message. Session Chat subsystem is not valid."));
    return;
    }

    // Only show the chat if the type is valid.
    if (SessionChatSubsystem->GetChatRoomType(RoomId) != CurrentChatRoomType)
    {
    return;
    }

    // Show the received chat message.
    AppendChatMessage(Message.Get());
    }
  4. GetLastChatMessages() 関数を以下のコードに置き換えて、現在選択されているチャットタイプに基づいてチャットメッセージ履歴を取得して表示します:

    void USessionChatWidget_Starter::GetLastChatMessages()
    {
    if (!SessionChatSubsystem)
    {
    UE_LOG_SESSIONCHAT(Warning, TEXT("Cannot get last chat messages. Session Chat subsystem is not valid."));
    return;
    }

    if (!ensure(GetOwningPlayer()))
    {
    UE_LOG_SESSIONCHAT(Warning, TEXT("Cannot get last chat messages. PlayerController is not valid."));
    return;
    }

    const ULocalPlayer* LocalPlayer = GetOwningPlayer()->GetLocalPlayer();
    if (!ensure(LocalPlayer))
    {
    UE_LOG_SESSIONCHAT(Warning, TEXT("Cannot get last chat messages. LocalPlayer is not valid."));
    return;
    }

    if (!ensure(W_ActiveChat))
    {
    UE_LOG_SESSIONCHAT(Warning, TEXT("Cannot get last chat messages. Chat widget component is not valid."));
    return;
    }

    // Get chat room id.
    FString ChatRoomId = SessionChatSubsystem->GetChatRoomIdBasedOnType(CurrentChatRoomType);

    // Abort if room id was not found.
    if (ChatRoomId.IsEmpty())
    {
    FText ChatRoomNotFoundMessage = INVALID_CHAT_ROOM_MESSAGE;
    switch (CurrentChatRoomType)
    {
    case EAccelByteChatRoomType::PARTY_V1:
    case EAccelByteChatRoomType::PARTY_V2:
    ChatRoomNotFoundMessage = INVALID_PARTY_CHAT_ROOM_MESSAGE;
    break;
    case EAccelByteChatRoomType::SESSION_V2:
    ChatRoomNotFoundMessage = INVALID_GAMESESSION_CHAT_ROOM_MESSAGE;
    break;
    }

    W_ActiveChat->SetWidgetState(EAccelByteWarsWidgetSwitcherState::Error, ChatRoomNotFoundMessage);
    return;
    }

    // Get last chat messages.
    TArray<TSharedRef<FChatMessage>> OutMessages;
    if (SessionChatSubsystem->GetLastChatMessages(
    LocalPlayer->GetPreferredUniqueNetId().GetUniqueNetId(),
    ChatRoomId,
    W_ActiveChat->GetMaxChatHistory(),
    OutMessages))
    {
    // Abort if last messages is empty.
    if (OutMessages.IsEmpty())
    {
    W_ActiveChat->SetWidgetState(EAccelByteWarsWidgetSwitcherState::Empty, NO_CHAT_MESSAGE);
    return;
    }

    // Display last chat messages.
    Algo::Reverse(OutMessages);
    for (const TSharedRef<FChatMessage>& Message : OutMessages)
    {
    AppendChatMessage(Message.Get());
    }
    }
    // Show error message if failed.
    else
    {
    W_ActiveChat->SetWidgetState(EAccelByteWarsWidgetSwitcherState::Error, FAILED_TO_LOAD_CHAT_MESSAGE);
    }
    }
  5. 次に、SwitchChatMessageType() 関数を以下のコードに置き換えて、ウィジェットチャットタイプが変更されたときにすぐにチャットメッセージ履歴を取得します:

    void USessionChatWidget_Starter::SwitchChatMessageType(const EAccelByteChatRoomType ChatRoomType)
    {
    // Switch chat message active panel based on type.
    switch(ChatRoomType)
    {
    case EAccelByteChatRoomType::SESSION_V2:
    Ws_ChatMessageType->SetActiveWidget(W_GameSessionChatOuter);
    W_ActiveChat = W_GameSessionChat;
    break;
    case EAccelByteChatRoomType::PARTY_V2:
    Ws_ChatMessageType->SetActiveWidget(W_PartyChatOuter);
    W_ActiveChat = W_PartyChat;
    break;
    }

    CurrentChatRoomType = ChatRoomType;

    // Try to display last chat messages if the current one is empty.
    if (W_ActiveChat)
    {
    W_ActiveChat->ClearChatMessages();
    W_ActiveChat->ClearInput();
    GetLastChatMessages();
    }
    }
  6. AppendChatMessage() 関数を以下のコードに置き換えて、追加の保護機能を備えた表示するチャットメッセージを追加します:

    void USessionChatWidget_Starter::AppendChatMessage(const FChatMessage& Message)
    {
    if (!SessionChatSubsystem)
    {
    UE_LOG_SESSIONCHAT(Warning, TEXT("Cannot append a chat message to display. Session Chat subsystem is not valid."));
    return;
    }

    if (!ensure(GetOwningPlayer()))
    {
    UE_LOG_SESSIONCHAT(Warning, TEXT("Cannot append a chat message to display. PlayerController is not valid."));
    return;
    }

    const ULocalPlayer* LocalPlayer = GetOwningPlayer()->GetLocalPlayer();
    if (!ensure(LocalPlayer))
    {
    UE_LOG_SESSIONCHAT(Warning, TEXT("Cannot append a chat message to display. LocalPlayer is not valid."));
    return;
    }

    const FUniqueNetIdAccelByteUserRef SenderABId = StaticCastSharedRef<const FUniqueNetIdAccelByteUser>(Message.GetUserId());
    if (!SenderABId.Get().IsValid())
    {
    UE_LOG_SESSIONCHAT(Warning, TEXT("Cannot append a chat message to display. Sender User Id is invalid."));
    return;
    }

    // Display chat message.
    UChatData* ChatData = NewObject<UChatData>();
    ChatData->Message = Message.GetBody();
    ChatData->bIsSenderLocal = SessionChatSubsystem->IsMessageFromLocalUser(LocalPlayer->GetPreferredUniqueNetId().GetUniqueNetId(), Message);

    // If the sender doesn't have display name, then use the default display name.
    ChatData->Sender = Message.GetNickname();
    if (ChatData->Sender.IsEmpty() || SenderABId.Get().GetAccelByteId().Equals(ChatData->Sender))
    {
    ChatData->Sender = UTutorialModuleOnlineUtility::GetUserDefaultDisplayName(Message.GetUserId().Get());
    }

    // Display chat message.
    W_ActiveChat->AppendChatMessage(ChatData);
    }
  7. 次に、チャットイベントをウィジェットにバインドしてコードを完成させます。これを行うには、事前定義された NativeOnActivated() 関数を次のコードに置き換えます:

    void USessionChatWidget_Starter::NativeOnActivated()
    {
    Super::NativeOnActivated();

    // Reset chat widget
    W_GameSessionChat->ClearChatMessages();
    W_GameSessionChat->ClearInput();
    W_PartyChat->ClearChatMessages();
    W_PartyChat->ClearInput();

    // Bind event to switch between chat message type.
    Btn_SessionChat->OnClicked().AddUObject(this, &ThisClass::SwitchChatMessageType, EAccelByteChatRoomType::SESSION_V2);
    Btn_PartyChat->OnClicked().AddUObject(this, &ThisClass::SwitchChatMessageType, EAccelByteChatRoomType::PARTY_V2);

    // Setup widget
    W_GameSessionChat->OnSubmitDelegates.AddUObject(this, &ThisClass::SendChatMessage);
    W_PartyChat->OnSubmitDelegates.AddUObject(this, &ThisClass::SendChatMessage);
    Btn_Back->OnClicked().AddUObject(this, &ThisClass::DeactivateWidget);

    // Bind chat events.
    if (SessionChatSubsystem)
    {
    SessionChatSubsystem->GetOnSendChatCompleteDelegates()->AddUObject(this, &ThisClass::OnSendChatComplete);
    SessionChatSubsystem->GetOnChatRoomMessageReceivedDelegates()->AddUObject(this, &ThisClass::OnChatRoomMessageReceived);
    }

    SwitchChatMessageType(CurrentChatRoomType);
    }
  8. 最後に、ウィジェットが閉じられたときにこれらのイベントをアンバインドします。これを行うには、事前定義された NativeOnDeactivated() 関数を次のコードに置き換えます:

    void USessionChatWidget_Starter::NativeOnDeactivated()
    {
    CurrentChatRoomType = EAccelByteChatRoomType::SESSION_V2;

    // Unbind chat events.
    if (SessionChatSubsystem)
    {
    SessionChatSubsystem->GetOnSendChatCompleteDelegates()->RemoveAll(this);
    SessionChatSubsystem->GetOnChatRoomMessageReceivedDelegates()->RemoveAll(this);
    }

    // Cleanup widget
    Btn_SessionChat->OnClicked().Clear();
    Btn_PartyChat->OnClicked().Clear();
    W_GameSessionChat->OnSubmitDelegates.RemoveAll(this);
    W_PartyChat->OnSubmitDelegates.RemoveAll(this);
    Btn_Back->OnClicked().RemoveAll(this);

    Super::NativeOnDeactivated();
    }

リソース