Unreal Chat

[ ue4  ]
Written on October 3, 2022

Setting up a basic chat system in an Unreal Engine multiplayer game is quite easy, as UE takes care of all the networking.

The chat system I’ve implemented is made up of two components - the ChatServer component, and the ChatClient component.

The server

The chat server is an actor component that lives on the game mode. This implies it only lives server side, which makes sense (in my mind, at least). The chat server has a Send method that sends a message to all chat clients.

void UChatServer::Send_Implementation(const FText& From, const FText& Message)
{
	for (auto It = GetWorld()->GetPlayerControllerIterator(); It; ++It)
	{
		auto Client = Cast<UChatClient>((*It)->GetComponentByClass(UChatClient::StaticClass()));
		Client->Receive(From, Message);
	}
}

The client

The client is an actor component that lives on the player controller, and is set to be replicated. It has both a Send method and a Receive method.

UChatClient::UChatClient()
{
	SetIsReplicatedByDefault(true);
}

The Send method is set to run on the server. Typically, it would be called from a blueprint in a UI widget on the client, but as it is replicated, and owned by the player controller it gets forwarded to the UE server. The chat client (now running on the UE server) find the chat server by looking for the component on the game mode and calls its Send method.

void UChatClient::Send_Implementation(const FText& Message)
{
	if (!ChatServer)
	{
		AGameModeBase* GameMode = GetWorld()->GetAuthGameMode();
		if (GameMode)
		{
			ChatServer = Cast<UChatServer>(GameMode->GetComponentByClass(UChatServer::StaticClass()));
		}
		else
		{
			UE_LOG(LogChatClient, Warning, TEXT("No game mode found"));
			ChatServer = nullptr;
		}
		if (!ChatServer)
		{
			UE_LOG(LogChatClient, Warning, TEXT("No chat server established"));
			return;
		}
	}
	if (!PlayerState)
	{
		PlayerState = Cast<APlayerController>(GetOwner())->GetPlayerState<APlayerState>();
		if (PlayerState)
		{
			MyName = FText::FromString(PlayerState->GetPlayerName());
		}
	}
	ChatServer->Send(MyName, Message);
}

The Receive method simply forwards the call to an event handler:

void UChatClient::Receive_Implementation(const FText& From, const FText& Message)
{
	OnMessageReceived.Broadcast(From, Message);
}

The UI

I’ve set up a very simple main screen:

Screenshot

The chat UI is added in BeginPlay of BP_UnrealChatHUD, which is set as the HUD for the game mode.

Hierarchy

ChatEntries is a VerticalBox that will receive a ChatEntry widget for each message received.

Input is an EditableTextBox to handle input from the player.

The MainUI has an event handler for On Text Committed on the input box:

OnTextCommitted OnTextCommitted

This takes the contents of the input box and sends it to the Send method of the chat client.

To show the messages, I bind an event to the chat client On Message Received event:

OnConstruct OnConstruct

I’ve tried to keep this sample as bare bones as possible - of course the UI needs a lot more work for a proper game, and the chat system needs features like filtering, blocking and so on, but I hope this demonstrates how simple the core of it is.

The project I used for this sample is available on Github:

https://github.com/snorristurluson/UnrealChat