UE:如何在蓝图中实现数据序列化与字节转换
前言
在UE项目中,网络通信、数据持久化、与外部程序交互是非常常见的需求。无论是通过UDP/TCP发送结构化数据,还是将游戏状态序列化为二进制存储,你都绑不开一个核心操作:将数据转换为字节数组。
然而在蓝图中,这件事并不简单:
- 蓝图没有原生的字节转换节点,int32、float、double 都无法直接转
TArray<uint8> - 结构体序列化更是难题,CustomThunk 对纯蓝图用户来说门槛太高
- UE自带的
FJsonObjectConverter序列化浮点数精度丢失严重 - 与 Python、C#、C++ 外部程序交换数据时,编码格式对不上
SimpleByteConversion 插件就是为了解决这些问题而生。
它提供了一套完整的蓝图节点,支持基础类型和任意结构体与字节数组/JSON字符串的双向转换,开箱即用。
一、核心功能
1.1 基础类型转换
插件覆盖了所有常用的基础类型,每种类型都提供 ToBytes 和 FromBytes 双向转换:
| 类型 | 转字节 | 从字节还原 |
|---|---|---|
| int32 | IntToBytes | BytesToInt |
| int64 | Int64ToBytes | BytesToInt64 |
| float | FloatToBytes | BytesToFloat |
| double | DoubleToBytes | BytesToDouble |
| bool | BoolToBytes | BytesToBool |
| FString | StringToBytes | BytesToString |
所有节点均为 BlueprintPure,可以直接在蓝图中作为纯函数使用,无需执行引脚。
实现原理:
// 以 int32 为例,直接内存拷贝,零开销
void ByteConverter::IntToBytes(int32 Value, TArray<uint8>& OutBytes)
{
OutBytes.SetNumUninitialized(sizeof(int32));
FMemory::Memcpy(OutBytes.GetData(), &Value, sizeof(int32));
}
所有基础类型都采用 FMemory::Memcpy 直接内存拷贝,性能最优。字符串转换使用 UTF-8 编码,自动处理 Null Terminator,确保跨平台兼容。
1.2 结构体序列化
这是插件最强大的功能——支持任意蓝图结构体与字节数组的双向转换:
StructToBytes/BytesToStruct— 二进制序列化StructToJsonString/JsonStringToStruct— JSON 字符串序列化
关键技术:CustomThunk
蓝图中无法直接传递泛型结构体,插件通过 CustomThunk + CustomStructureParam 实现了通用的结构体参数:
UFUNCTION(BlueprintPure, CustomThunk,
meta = (CustomStructureParam = "Struct", DisplayName = "Struct To Bytes"),
Category = "SimpleByteConversion|Struct")
static void StructToBytes(const int32& Struct, TArray<uint8>& Bytes);
DECLARE_FUNCTION(execStructToBytes);
这意味着你可以在蓝图中直接拖入任何自定义结构体,插件会自动识别其类型并完成序列化。
1.3 高精度 JSON 转换
UE 默认的 JSON 序列化存在两个问题:
- 字段名带有引擎内部后缀(如
MyField_5_A3B2C1D4) - 浮点数精度丢失(float 只保留6位有效数字)
插件通过自定义 FExactPrintPolicy 和字段名清洗解决了这两个问题:
// 高精度输出:float 保留9位,double 保留17位
template <typename CharT>
struct FExactPrintPolicy : TCondensedJsonPrintPolicy<CharT>
{
static void WriteFloat(FArchive* Stream, float V)
{
FString S = FString::Printf(TEXT("%.9f"), V);
TCondensedJsonPrintPolicy<CharT>::WriteString(Stream, S);
}
static void WriteDouble(FArchive* Stream, double V)
{
FString S = FString::Printf(TEXT("%.17g"), V);
TCondensedJsonPrintPolicy<CharT>::WriteString(Stream, S);
}
};
输出的 JSON 字段名干净、数值精度完整,可以直接被 Python、C# 等外部程序解析。
二、使用场景
场景1:UDP/TCP 网络通信
当你使用 SimpleUDP 或 SimpleTCPClient 发送数据时,需要将结构化数据编码为字节数组:
1. 定义一个结构体(如 FPlayerState:位置、血量、状态)
2. 使用 StructToBytes 将结构体转为 TArray<uint8>
3. 通过 UDP/TCP 发送字节数组
4. 接收端使用 BytesToStruct 还原为结构体
场景2:与 Python 程序交换数据
使用 JSON 格式进行跨语言数据交换:
1. UE 端:StructToJsonString 将游戏数据转为 JSON 字符串
2. 通过 TCP/WebSocket 发送给 Python 程序
3. Python 端:json.loads() 直接解析
4. 反向同理:Python json.dumps() → UE JsonStringToStruct
场景3:数据持久化
将游戏存档序列化为二进制文件:
1. 将存档结构体通过 StructToBytes 转为字节数组
2. 使用 FFileHelper::SaveArrayToFile 写入磁盘
3. 读取时 FFileHelper::LoadFileToArray 加载字节数组
4. BytesToStruct 还原为存档结构体
三、快速上手
步骤1:安装插件
将插件文件夹复制到项目的 Plugins 目录,重启编辑器。
步骤2:在蓝图中使用
所有节点都在 SimpleByteConversion 分类下:
- 基础类型:搜索
IntToBytes、FloatToBytes等 - 结构体:搜索
StructToBytes、StructToJsonString等
步骤3:C++ 中使用
如果你在 C++ 中需要使用,可以直接调用 ByteConverter 工具类:
#include "ByteConverter.h"
// 基础类型
TArray<uint8> Bytes;
ByteConverter::IntToBytes(42, Bytes);
// 结构体
FMyStruct Data;
ByteConverter::StructToBytes(&Data, FMyStruct::StaticStruct(), Bytes);
// JSON
FString JsonStr;
ByteConverter::StructToJsonString(&Data, FMyStruct::StaticStruct(), JsonStr);
四、插件获取
适用版本: Unreal Engine 5.2+
获取方式: 在 Fab 商店搜索 SimpleByteConversion 即可找到
有任何问题欢迎在评论区交流。
总结
SimpleByteConversion 解决了 UE 蓝图中数据序列化的核心痛点:
- 基础类型:int32/int64/float/double/bool/FString 与字节数组双向转换
- 结构体:任意蓝图结构体的二进制和 JSON 序列化
- 高精度:自定义输出策略,浮点数精度不丢失
- 跨语言:干净的 JSON 输出,方便与外部程序交互
无论你是做网络通信、数据持久化还是跨语言数据交换,这个插件都能帮你省去大量的底层编码工作。
感谢阅读,欢迎点赞、关注、收藏,有问题可在评论区交流。
如果本文对你有帮助,点击这里捐赠支持作者。