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

Adding private chat UI - Private 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 private chats. The widgets are available in the Resources section and include the following:

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

    • Header file: /Source/AccelByteWars/TutorialModules/Social/PrivateChat/UI/PrivateChatWidget_Starter.h
    • CPP file: /Source/AccelByteWars/TutorialModules/Social/PrivateChat/UI/PrivateChatWidget_Starter.cpp
    • Blueprint widget: /Content/TutorialModules/Social/PrivateChat/UI/W_PrivateChat_Starter.uasset
  • ChatWidget: A C++ class used within PrivateChatWidget_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.

Private Chat widget

This widget primarily consists of the W_Chat Blueprint widget, which handles both input and display of the chat. This is where you will manipulate W_Chat to display and send actual chat messages.

Private chat widget Unreal Byte Wars private chat

The widget component is declared in the header file:

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

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 private 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 private 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 PrivateChatWidget_Starter class header file. Then, declare the following functions.

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

    UFUNCTION()
    void SendPrivateChatMessage(const FText& MessageText);
    void OnSendPrivateChatComplete(FString UserId, FString MsgBody, FString RoomId, bool bWasSuccessful);

    void OnPrivateChatMessageReceived(const FUniqueNetId& UserId, const TSharedRef<FChatMessage>& Message);

    void GetLastPrivateChatMessages() const;
  2. Open the PrivateChatWidget_Starter class CPP file and define the AppendChatMessage() function to append chat messages to be displayed.

    void UPrivateChatWidget_Starter::AppendChatMessage(const FChatMessage& Message) const
    {
    // ...
    if (!ensure(GetOwningPlayer()))
    {
    UE_LOG_PRIVATECHAT(Warning, TEXT("Cannot append a private chat message to display. PlayerController is not valid."));
    return;
    }

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

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

    // Construct 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_Chat->AppendChatMessage(ChatData);
    }
  3. Still in the CPP file, define the SendPrivateChatMessage() function. You will use this function to send the chat message. For now, add this code as a safeguard:

    void UPrivateChatWidget_Starter::SendPrivateChatMessage(const FText& MessageText)
    {
    // ...
    if (!ensure(GetOwningPlayer()))
    {
    UE_LOG_PRIVATECHAT(Warning, TEXT("Cannot send private chat message. PlayerController is not valid."));
    return;
    }

    const ULocalPlayer* LocalPlayer = GetOwningPlayer()->GetLocalPlayer();
    if (!ensure(LocalPlayer))
    {
    UE_LOG_PRIVATECHAT(Warning, TEXT("Cannot send private chat message. LocalPlayer is not valid."));
    return;
    }
    // ...
    }
  4. Next, define the OnSendPrivateChatComplete() 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 UPrivateChatWidget_Starter::OnSendPrivateChatComplete(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_Chat->AppendChatMessage(ChatData);
    }
  5. Define the OnPrivateChatMessageReceived() 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 UPrivateChatWidget_Starter::OnPrivateChatMessageReceived(const FUniqueNetId& UserId, const TSharedRef<FChatMessage>& Message)
    {
    // Show the received chat message.
    AppendChatMessage(Message.Get());
    }
  6. Lastly, add the GetLastPrivateChatMessages() 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 UPrivateChatWidget_Starter::GetLastPrivateChatMessages() const
    {
    // ...
    if (!ensure(GetOwningPlayer()))
    {
    UE_LOG_PRIVATECHAT(Warning, TEXT("Cannot get last private chat messages. PlayerController is not valid."));
    return;
    }

    const ULocalPlayer* LocalPlayer = GetOwningPlayer()->GetLocalPlayer();
    if (!ensure(LocalPlayer))
    {
    UE_LOG_PRIVATECHAT(Warning, TEXT("Cannot get last private chat messages. LocalPlayer 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/PrivateChat/ and open the DA_PrivateChat 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 private chat widget.

Resources