记录UE4中WebSocket和Json的使用方法(C++使用,蓝图没有的,想在蓝图用可以C++暴露方法给蓝图)。本文记录如何在UE4中使用Json来进行解析和写入。
内容:
- UE4 WebSocket Client
- Python WebSocket Server
- UE4 Json
UE4.25.3。项目github:
https://github.com/tiax615/UE4_Networkgithub.com3. UE4 Json
在实际工作和学习中,Json是一个很常用的数据格式,不错的可读性,多语言的支持让Json广泛使用。
UE4中,Json使用也不复杂,百度一下能找到不错的参考。在第1步中实现了UE4WebSocketClient,在第2步中实现了PythonWebSocketServer,并接收了Client发送来的字符串,向Client发送了Json格式的字符串。第3步将记录如何在UE4中解析和生成Json。
3.1. 增加模块
和WebSockets模块一样,也需要在项目名.build.cs中新增Json模块
// Copyright Epic Games, Inc. All Rights Reserved.
using UnrealBuildTool;
public class UE4_Network : ModuleRules
{
public UE4_Network(ReadOnlyTargetRules Target) : base(Target)
{
PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;
PublicDependencyModuleNames.AddRange(new string[]
{
"Core", "CoreUObject", "Engine", "InputCore",
"WebSockets", "Json"
});
PrivateDependencyModuleNames.AddRange(new string[] { });
// Uncomment if you are using Slate UI
// PrivateDependencyModuleNames.AddRange(new string[] { "Slate", "SlateCore" });
// Uncomment if you are using online features
// PrivateDependencyModuleNames.Add("OnlineSubsystem");
// To include OnlineSubsystemSteam, add it to the plugins section in your uproject file with the Enabled attribute set to true
}
}
3.2. 修改Server
在第2步中,使用send_time()发送的Json中Value为一串string,还可以发送其他类型的数据,例如string/bool/number/array等。在Python的服务类中,新增下面这个方法send_something,发送各种类型的数据(一个包bool/int/float/string的array)。发送的something字符串,包含Topic和Data,其中Data中又包好Key和Value。
# 发送各类型数据
def send_something(self):
self._add_cmd('Unreal','Something',[False,66,123.4,"str"])
改写main函数,发送一次time,再发送一次something
def main():
s=MyServer('127.0.0.1',23333)
s.start_server()
s.send_time()
s.send_something()
运行Server,运行Client,结果如下。各自收发成功,但UE4也只当这是个字符串,没有做任何解析。
3.3. 解析Json
在.h中新增一个解析的方法JsonParse(),在OnMessage事件中调用这个解析:
// .h
protected:
//...
void JsonParse(const FString InMessage);
在JsonParse()的实现中,先定义RootObj和JsonReader,用JsonReader反序列化这个FJsonObject类型的对象。获取Topic和Key,根据Key来判断做何解析。如果Key是Time,就认为Value的值的字符串;如果Key是Something,就认为Value的值是Array,而Array的每个元素又可以解析成不同类型的数据。
// .cpp
void AActorWebSocket::OnMessage(const FString& Message)
{
UE_LOG(LogTemp,Warning,TEXT("%s Message:%s"),*FString(__FUNCTION__),*Message);
JsonParse(Message);
}
void AActorWebSocket::JsonParse(const FString InMessage)
{
TSharedPtr<FJsonObject> RootObj=MakeShareable(new FJsonObject());
TSharedRef<TJsonReader<>> JsonReader=TJsonReaderFactory<>::Create(InMessage);
if(FJsonSerializer::Deserialize(JsonReader,RootObj)) // 通过JsonReader读取RootObj
{
FString Topic=RootObj->GetStringField("Topic"); // Topic
UE_LOG(LogTemp,Warning,TEXT("%s Topic:%s"),*FString(__FUNCTION__),*Topic);
TSharedPtr<FJsonObject> DataObj=MakeShareable(new FJsonObject());
DataObj=RootObj->GetObjectField("Data"); // Data
FString Key=DataObj->GetStringField("Key"); // Key
UE_LOG(LogTemp,Warning,TEXT("%s Key:%s"),*FString(__FUNCTION__),*Key);
if(Key.Equals("Time"))
{
FString Time=DataObj->GetStringField("Value"); // Value type is String
UE_LOG(LogTemp,Warning,TEXT("%s Time:%s"),*FString(__FUNCTION__),*Time);
}
else if(Key.Equals("Something"))
{
TArray<TSharedPtr<FJsonValue>> Value=DataObj->GetArrayField("Value"); // Value type is Array
bool BoolValue=Value[0]->AsBool();
int IntValue=Value[1]->AsNumber();
float FloatValue=Value[2]->AsNumber();
FString StringValue=Value[3]->AsString();
UE_LOG(LogTemp,Warning,TEXT("%s BoolValue:%d"),*FString(__FUNCTION__),BoolValue);
UE_LOG(LogTemp,Warning,TEXT("%s IntValue:%d"),*FString(__FUNCTION__),IntValue);
UE_LOG(LogTemp,Warning,TEXT("%s FloatValue:%f"),*FString(__FUNCTION__),FloatValue);
UE_LOG(LogTemp,Warning,TEXT("%s StringValue:%s"),*FString(__FUNCTION__),*StringValue);
}
}
}
测试结果如下,UE4已经能分别解析Json中各类型的数据了。
3.4. 写入Json
现在UE4能接收到消息,并且作为Json来解析了。下面记录如何序列化写入Json,并发送出去给Server,让Server能够解析。
修改MySend(),初始化一个TSharedPtr<FJsonObject>类型的RootObj,给他新增几个字段。其中IsExecute字段的值是bool,Type字段的值是String,Value字段的值是JsonValue类型
void AActorWebSocket::MySend()
{
TSharedPtr<FJsonObject> RootObj=MakeShareable(new FJsonObject);
RootObj->SetBoolField("IsExecute",true);
RootObj->SetStringField("Type","Test");
TSharedPtr<FJsonValue> Value=MakeShareable(new FJsonValueNumber(GetGameTimeSinceCreation()));
RootObj->SetField("Value",Value);
FString JsonStr;
TSharedRef<TJsonWriter<TCHAR>> JsonWriter=TJsonWriterFactory<TCHAR>::Create(&JsonStr);
FJsonSerializer::Serialize(RootObj.ToSharedRef(),JsonWriter);
if(Socket->IsConnected())
{
// Socket->Send(FString::SanitizeFloat(GetGameTimeSinceCreation()));
Socket->Send(JsonStr);
}
UE_LOG(LogTemp,Warning,TEXT("%s Result:%s"),*FString(__FUNCTION__),*JsonStr);
}
修改PythonWebSocketServer中的接收方法,简单解析收到的消息:
# 接收处理
async def __consumer(self,message):
print('recv message: {0}'.format(message))
self.__isExecute=True
jsonContent=json.loads(message)
self.__isExecute=jsonContent['IsExecute']
self.__message_value=jsonContent['Value']
print('IsExecute',jsonContent['IsExecute'])
print('Type',jsonContent['Type'])
print('Value',jsonContent['Value'])
测试,UE4成功发送Json,Python服务成功接收了Json并解析。
以上就实现了UE4中Json的解析和写入,代码还算简洁,但肯定有更优雅的方式。记录在此抛砖引玉~感谢阅读!
天剑行风:UE4_使用WebSocket和Json(上)zhuanlan.zhihu.com999. Ref
- UE4读写Json文件:https://blog.csdn.net/qq_39108291/article/details/102944396
- 项目github:https://github.com/tiax615/UE4_Network
本文原创,如需转载,请注明出处。欢迎讨论,谢谢!