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

Adding session chat UI - Session chat - (Unreal Engine module)

Last updated on September 4, 2025

What's on the menu

In this tutorial, you will learn how to prepare widgets used to display and send session chats. The widgets are available in the Resources section and include the following:

  • SessionChatWidget_Starter: A C++ class used to display and send chat messages.

    • Header file: /Source/AccelByteWars/TutorialModules/Social/SessionChat/UI/SessionChatWidget_Starter.h
    • CPP file: /Source/AccelByteWars/TutorialModules/Social/SessionChat/UI/SessionChatWidget_Starter.cpp
    • Blueprint widget: /Content/TutorialModules/Social/SessionChat/UI/W_SessionChat_Starter.uasset
  • ChatWidget: A C++ class used within SessionChatWidget_Starter to display all chat entries and receive user input for messages to be sent.

    • Header file: /Source/AccelByteWars/TutorialModules/Social/ChatEssentials/UI/ChatWidget.h
    • CPP file: /Source/AccelByteWars/TutorialModules/Social/ChatEssentials/UI/ChatWidget.cpp
    • Blueprint widget: /Content/TutorialModules/Social/ChatEssentials/UI/W_Chat.uasset
  • ChatWidgetEntry: A C++ class used within ChatWidget to display individual chat message entries.

    • Header file: /Source/AccelByteWars/TutorialModules/Social/ChatEssentials/UI/ChatWidgetEntry.h
    • CPP file: /Source/AccelByteWars/TutorialModules/Social/ChatEssentials/UI/ChatWidgetEntry.cpp
    • Blueprint widget: /Content/TutorialModules/Social/ChatEssentials/UI/W_ChatEntry.uasset

Refer to the following sections for more details on how these widgets are constructed.

Session Chat widget

This widget primarly contains two instances of ChatWidget class with several helper variables to switch between game session chat and party chat and display the chat messages accordingly.

Game session chat widget Unreal Byte Wars session chat

Party session chat widget Unreal Byte Wars session chat

The widget components are declared in the header file:

protected:
// ...
EAccelByteChatRoomType CurrentChatRoomType = EAccelByteChatRoomType::SESSION_V2;

UPROPERTY()
UChatWidget* W_ActiveChat = nullptr;

UPROPERTY(BlueprintReadOnly, meta = (BindWidgetOptional, BlueprintProtected = true, AllowPrivateAccess = true))
UWidgetSwitcher* Ws_ChatMessageType;

UPROPERTY(BlueprintReadOnly, meta = (BindWidgetOptional, BlueprintProtected = true, AllowPrivateAccess = true))
UCommonButtonBase* Btn_Back;

#pragma region Game Session Chat
UPROPERTY(BlueprintReadOnly, meta = (BindWidgetOptional, BlueprintProtected = true, AllowPrivateAccess = true))
UWidget* W_GameSessionChatOuter;

UPROPERTY(BlueprintReadOnly, meta = (BindWidgetOptional, BlueprintProtected = true, AllowPrivateAccess = true))
UChatWidget* W_GameSessionChat;

UPROPERTY(BlueprintReadOnly, meta = (BindWidgetOptional, BlueprintProtected = true, AllowPrivateAccess = true))
UCommonButtonBase* Btn_SessionChat;
#pragma endregion

#pragma region Party Chat
UPROPERTY(BlueprintReadOnly, meta = (BindWidgetOptional, BlueprintProtected = true, AllowPrivateAccess = true))
UWidget* W_PartyChatOuter;

UPROPERTY(BlueprintReadOnly, meta = (BindWidgetOptional, BlueprintProtected = true, AllowPrivateAccess = true))
UChatWidget* W_PartyChat;

UPROPERTY(BlueprintReadOnly, meta = (BindWidgetOptional, BlueprintProtected = true, AllowPrivateAccess = true))
UCommonButtonBase* Btn_PartyChat;
#pragma endregion

To switch between game session chat and party chat, we can use the SwitchChatMessageType() helper function. The CurrentChatRoomType is the helper variable to store the widget status, whether it is currently in the game session chat or party chat. If the current active chat is game session chat, the W_GameSessionChat will be displayed, otherwise it will display W_PartyChat to display the party chat. The active chat widget then be stored in the W_ActiveChat helper variable for easy access.

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;
// ...
}

Chat widget

This widget contains an AccelByteWarsWidgetSwitcher, which is a custom Widget Switcher with a predefined state. It includes an editable text box for chat input, a list view to display chat message entries, and a button to send the message.

Chat widget Unreal Byte Wars session chat

The widget components are declared in the Header file:

private:
// ...
UPROPERTY(BlueprintReadOnly, meta = (BindWidgetOptional, BlueprintProtected = true, AllowPrivateAccess = true))
UAccelByteWarsWidgetSwitcher* Ws_ChatMessage;

UPROPERTY(BlueprintReadOnly, meta = (BindWidgetOptional, BlueprintProtected = true, AllowPrivateAccess = true))
UEditableText* Edt_ChatMessage;

UPROPERTY(BlueprintReadOnly, meta = (BindWidgetOptional, BlueprintProtected = true, AllowPrivateAccess = true))
UListView* Lv_ChatMessage;

UPROPERTY(BlueprintReadOnly, meta = (BindWidgetOptional, BlueprintProtected = true, AllowPrivateAccess = true))
UCommonButtonBase* Btn_Send;

This widget includes several functions and a delegate that allow other widgets to control what it displays and to receive player input. These functions and the delegate are declared in the header file:

public:
// ...
void AppendChatMessage(UChatData* ChatData) const;
// ...
void ClearChatMessages() const;
// ...
void ClearInput() const;
// ...
void SetWidgetState(const EAccelByteWarsWidgetSwitcherState State, const FText& StateMessage = FText::GetEmpty()) const;
// ...
int32 GetMaxChatHistory() const { return MaxChatHistory; }
// ...
FChatOnSubmit OnSubmitDelegates;
  • AppendChatMessage: Adds a chat entry.
  • ClearChatMessages: Clears the currently displayed chat entries.
  • ClearInput: Clears the input editable text.
  • SetWidgetState: Sets the widget state to loading, error, empty, or not empty, which determines the visibility of chat entries and input text.
  • GetMaxChatHistory: Retrieves the predefined MaxChatHistory value.
  • OnSubmitDelegates: A delegate that is called when the player presses enter while typing a message or clicks the Send button.

Also, take note of these variables:

protected:
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
int32 MaxChatHistory = 10000;

UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
float SendChatCooldown = 1.0f;

// Based on the default value of chat character limit on Admin Portal
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
int32 MaxMessageLength = 500;
  • MaxChatHistory: This is used later to limit how many chats should be retrieved from the backend.
  • SendChatCooldown: Controls how long the editable text and send button are disabled after the player sends a chat, preventing message spamming from the game client.
  • MaxMessageLength: Controls the maximum length of the message that can be sent. This can also be configured on the backend, which will be covered later.

Chat Entry widget

This widget consists of text to display the chat sender's name and the message.

Chat entry widget Unreal Byte Wars session chat

The components above are declared in the header file:

protected:
// ...
UPROPERTY(BlueprintReadOnly, meta = (BindWidgetOptional, BlueprintProtected = true, AllowPrivateAccess = true))
UTextBlock* Tb_Sender;

UPROPERTY(BlueprintReadOnly, meta = (BindWidgetOptional, BlueprintProtected = true, AllowPrivateAccess = true))
UTextBlock* Tb_Message;

Ready the UI

In this section, you will learn how to prepare the widgets mentioned earlier so you can follow along with the tutorial.

  1. Open the SessionChatWidget_Starter class header file. Then, declare the following functions.

    protected:
    // ...
    void AppendChatMessage(const FChatMessage& Message);

    void SendChatMessage(const FText& MessageText);

    void GetLastChatMessages();

    void OnSendChatComplete(FString UserId, FString MsgBody, FString RoomId, bool bWasSuccessful);
    void OnChatRoomMessageReceived(const FUniqueNetId& UserId, const FChatRoomId& RoomId, const TSharedRef<FChatMessage>& Message);
  2. Open the SessionChatWidget_Starter class CPP file and define the AppendChatMessage() function to append chat messages to be displayed.

    void USessionChatWidget_Starter::AppendChatMessage(const FChatMessage& Message)
    {
    // ...
    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();
    // ...
    // 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);
    }
  3. Still in the CPP file, define the SendChatMessage() function. You will use this function to send the chat message. For now, add this code as a safeguard:

    void USessionChatWidget_Starter::SendChatMessage(const FText& MessageText)
    {
    // ...
    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;
    }
    // ...
    }
  4. Next, define the OnSendChatComplete() function. You will use this function as a callback when a new chat message is sent. This function appends the new message to be displayed.

    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;
    }
    // ...
    // Display the chat if success.
    UChatData* ChatData = NewObject<UChatData>();
    ChatData->Message = MsgBody;
    ChatData->bIsSenderLocal = true;
    W_ActiveChat->AppendChatMessage(ChatData);
    }
  5. Define the OnChatRoomMessageReceived() function. You will use this function as a callback when a new chat message is received. This function appends the new message to be displayed.

    void USessionChatWidget_Starter::OnChatRoomMessageReceived(const FUniqueNetId& UserId, const FChatRoomId& RoomId, const TSharedRef<FChatMessage>& Message)
    {
    // ...
    // Show the received chat message.
    AppendChatMessage(Message.Get());
    }
  6. Lastly, add the GetLastChatMessages() function. You will use this function to retrieve the messages that the player received when they are not in the chat menu. For now, add this safeguard code:

    void USessionChatWidget_Starter::GetLastChatMessages()
    {
    // ...
    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;
    }
    // ...
    }
  7. Build the project and open it in the Unreal Editor.

  8. In the editor, from the content browser, navigate to /Content/TutorialModules/Social/SessionChat/ and open the DA_SessionChat data asset. Make sure to enable the Is Active and Is Starter Mode Active options, then save the data asset. This will activate the widgets you just prepared.

  9. Play the game in the Editor. Log in, and you should be able to navigate to Social > Friends > choose any friend > Chat to open the session chat widget.

Resources