UE4 C++ 多人游戏中的简单聊天窗口

本质

不管是客户端还是服务器在输入文字后,按下回车发送,将触发RPC调用。然后通过RPC将发送者,输入文本等信息,传入到服务器,然后通过多播RPC传播到所有客户端的聊天框。

UI

UI利用三个组件

ScrollBox

用于在服务器以及每个客户端上显示消息的载体

TextBlock

本地将信息通过一个一个的TextBlock组装,然后将组装的结果添加到ScrollBox中实现消息的显示

UEditableText

每个机器上编辑发送消息的主体,该组件具有OnTextCommitted的委托,可以处理提交事件,可以在自定义一个OnSendText委托,用于当Committed时可以外部调用。

switch (CommitMethod)
	{
	case ETextCommit::Default:
		break;
	case ETextCommit::OnEnter:
		UE_LOG(LogTemp, Warning, TEXT("TextCommitted_OnEnter"));
		OnSendText.Broadcast(Text);
		SendText->SetText(FText::FromString(""));
		UGameplayStatics::GetPlayerController(GetWorld(), 0)->SetInputMode(FInputModeGameOnly());
		GetNowUserComponent(GetOwningPlayer())->ToggleChatWindow();
		break;
	case ETextCommit::OnUserMovedFocus:
		break;
	case ETextCommit::OnCleared:
		break;
	default:
		break;
	}

实现

将直接在GameMode中的PlayerController中增加用于Chat的Component。

ServerSentText

该函数是一个ServerRPC,当接受到OnSendText委托后,调用。
在函数内部,通过遍历当前World中具有ChatComponent的Controller,获得所有客户端的Actor。然后调用多播RPC实现消息的滚动

TArray<AActor*> Actors;
UGameplayStatics::GetAllActorsOfClass(GetWorld(), AXBlasterPlayerController::StaticClass(), Actors);
for (auto& it : Actors)
{
	UActorComponent* cont = it->GetComponentByClass(UXChatComponent::StaticClass());
	if (cont && cont->Implements<UXChatInterface>())
	{
		IXChatInterface::Execute_ChatMessage(
			cont,
			Message,
			MessageType,
			PlayerName,
			SetMessageTypeColor(MessageType),
			ChatType
		);
	}
}

多播RPC MultiSendMessage

该函数在服务器上调用后,会在每个客户端进行执行,该函数主要处理发送信息的整合。
通过GetOwner()获取当前的Controller,然后判断Controller是不是本地的,如果不是那么就会跳过,只有是本地的才会进行消息的拼装,否则会出现多条相同的消息

	AXBlasterPlayerController* PIC = Cast<AXBlasterPlayerController>(GetOwner());
	if (!PIC->IsLocalController()) return;
	AXBlasterHUD* HUD = Cast<AXBlasterHUD>(PIC->GetHUD());
	if (HUD)
	{
		if (HUD->ChatWdg)
		{
			UXTextWidget* TextWidget = CreateWidget<UXTextWidget>(
				UGameplayStatics::GetPlayerController(GetWorld(), 0),
				HUD->ChatTextClass
			);
			if (TextWidget)
			{
				TextWidget->PlayerName = FText::FromString(SendName);
				TextWidget->InText = Message;
				TextWidget->MessType = MessageType;
				TextWidget->ChatType = EChatTypes::ECT_All;
				HUD->ChatWdg->ChatScrollBox->AddChild(TextWidget);
				HUD->ChatWdg->ChatScrollBox->ScrollToEnd();
			}
		}
	}

通过接口实现多播RPC的调用

由于在Server里是遍历了World中所有的Controller,使用接口可以表面获取实例来进行调用而且可以放置选择到那些没有Chat功能的Controller,因为在C++中会首先检验当前的实例是否实现了接口

if (cont && cont->Implements<UXChatInterface>())
	{
		IXChatInterface::Execute_ChatMessage(
			cont,
			Message,
			MessageType,
			PlayerName,
			SetMessageTypeColor(MessageType),
			ChatType
		);
	}

作者:XTG111

出处:https://www.cnblogs.com/XTG111/p/18279872

版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。

posted @   XTG111  阅读(28)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
more_horiz
keyboard_arrow_up light_mode palette
选择主题
点击右上角即可分享
微信分享提示