# 实现目标
- ue5 c++ 实现socket客户端,读取服务端数据,并进行解析
#实现步骤
- {projectName}.Build.cs里增加 "WebSockets","JsonUtilities", "Json"配置信息,最终输出如下:
using UnrealBuildTool; public class myue521 : ModuleRules { public myue521(ReadOnlyTargetRules Target) : base(Target) { PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs; PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore" , "HeadMountedDisplay", "EnhancedInput" , "WebSockets","JsonUtilities", "Json"}); } }
说明,其中myue521是我的模块名,文件名为myue521.Build.cs。 新增的模块:"WebSockets","JsonUtilities", "Json"。
-
准备实现自己的webscoket_client。具体操作步骤如下:
-
在ue5中自定义类,父类设置为UGameInstance,我这命名为UUWebSocketGameInstance
-
在UUWebSocketGameInstance.h里新增如下方法。
-
其中init和 Shutdown方法是在父类UGameInstance中定义的,我们这里覆盖它;
-
WebSocket用来标识我们代码生成的socket,计划在init里初始化,在Shutdown里销毁
-
OnConnected、OnConnectionError、OnClosed、OnMessage、OnMessageSent用来处理socket消息,具体看后买你的代码实现。
-
-
在UUWebSocketGameInstance.cpp里实现已经生命的方法。
// Fill out your copyright notice in the Description page of Project Settings. #include "UWebSocketGameInstance.h" #include "WebSockets/Public/WebSocketsModule.h" #include "WebSockets/Public/IWebSocket.h" #include "Templates/SharedPointer.h" void UUWebSocketGameInstance::Init() { Super::Init(); if (!FModuleManager::Get().IsModuleLoaded("WebSockets")) { FModuleManager::Get().LoadModule("WebSockets"); } WebSocket = FWebSocketsModule::Get().CreateWebSocket("ws://127.0.0.1:8081/webSocketServer/ue"); WebSocket->OnConnected().AddUObject(this, &UUWebSocketGameInstance::OnConnected); WebSocket->OnConnectionError().AddUObject(this, &UUWebSocketGameInstance::OnConnectionError); WebSocket->OnClosed().AddUObject(this, &UUWebSocketGameInstance::OnClosed); WebSocket->OnMessage().AddUObject(this, &UUWebSocketGameInstance::OnMessage); WebSocket->OnMessageSent().AddUObject(this, &UUWebSocketGameInstance::OnMessageSent); WebSocket->Connect(); } void UUWebSocketGameInstance::Shutdown() { if (WebSocket->IsConnected()) { WebSocket->Close(); } Super::Shutdown(); } void UUWebSocketGameInstance::OnConnected() { UE_LOG(LogTemp, Warning, TEXT("%s"), *FString(__FUNCTION__)); GEngine->AddOnScreenDebugMessage(-1, 3.0f, FColor::Green, "Successfully Connected"); } void UUWebSocketGameInstance::OnConnectionError(const FString& Error) { UE_LOG(LogTemp, Warning, TEXT("%s Error:%s"), *FString(__FUNCTION__), *Error); } void UUWebSocketGameInstance::OnClosed(int32 StatusCode, const FString& Reason, bool bWasClean) { UE_LOG(LogTemp, Warning, TEXT("%s StatusCode:%d Reason:%s bWasClean:%d"), *FString(__FUNCTION__), StatusCode, *Reason, bWasClean); } void UUWebSocketGameInstance::OnMessage(const FString& Message) { GEngine->AddOnScreenDebugMessage(-1, 3.0f, FColor::Cyan, FString::Printf(TEXT("%s Message:%s"), *FString(__FUNCTION__), *Message) ); UE_LOG(LogTemp, Warning, TEXT("%s Message:%s"), *FString(__FUNCTION__), *Message); TSharedRef< TJsonReader<> > Reader = TJsonReaderFactory<>::Create(Message); TSharedPtr<FJsonObject> Root; if (FJsonSerializer::Deserialize(Reader, Root)) { if (Root->HasField(TEXT("Topic"))) { FString Topic = Root->GetStringField(TEXT("Topic")); TSharedPtr<FJsonObject, ESPMode::ThreadSafe> Data = Root->GetObjectField(TEXT("Data")); // TSharedPtr<FJsonObject, ESPMode::ThreadSafe> ObjectField = Object->GetObjectField(TEXT("realtime")); FString KeyField = Data->GetStringField("Key"); FString ValueField = Data->GetStringField("Value"); GEngine->AddOnScreenDebugMessage(-1, 3.0f, FColor::Cyan, "Key: " + KeyField + ",Value:" + ValueField); } else { GEngine->AddOnScreenDebugMessage(-1, 3.0f, FColor::Cyan, "解析json异常"); } } } void UUWebSocketGameInstance::OnMessageSent(const FString& MessageString) { UE_LOG(LogTemp, Warning, TEXT("%s MessageString:%s"), *FString(__FUNCTION__), *MessageString); }
-
其中UUWebSocketGameInstance::Init()里初始化了websocket,并配置监听方法
-
UUWebSocketGameInstance::Shutdown()用来销毁生成的websocket
-
UUWebSocketGameInstance::OnConnected(),UUWebSocketGameInstance::OnConnectionError,UUWebSocketGameInstance::OnClosed,UUWebSocketGameInstance::OnMessage,UUWebSocketGameInstance::OnMessageSent是用来处理绑定消息的。其中UUWebSocketGameInstance::OnMessage里的消息是json格式,具体格式见下面的备注1.
-
-
-
开始配置使用并调用方法。
-
自主调用可以在某个Character里通过如下代码进行调用。可以在自己的类里面调用。比如放到构造方法或者某个动作触发调用。
void Amyue521Character::NotifyServer() { UUWebSocketGameInstance* GameInstance = Cast<UUWebSocketGameInstance>(GetGameInstance()); if (GameInstance) { if (GameInstance->WebSocket->IsConnected()) { GameInstance->WebSocket->Send("FROM UnrealEngine 5"); } } }
-
通过UE5的项目设置进行修改游戏实例。
-
-
备注
-
约定接收的json数据格式为
{ "Topic": "Unreal", "Data": { "Key": "mood", "Value": 1.0 } }
-
-
总结
-
通过该例子我们学到了websocket,json的应用
-
还学到的两种打印log的方法
GEngine->AddOnScreenDebugMessage(-1, 3.0f, FColor::Cyan, FString::Printf(TEXT("%s Message:%s"), *FString(__FUNCTION__), *Message) ); UE_LOG(LogTemp, Warning, TEXT("%s Message:%s"), *FString(__FUNCTION__), *Message);
-
-
待解决的问题
-
为什么使用UGameInstance, UGameInstance在UE5中充当什么角色
-
ULog 的使用,参考文档:http://www.bimant.com/blog/ue_log-crash-course/
-