UE4 数据压缩方法(一)

导语
对于一个多人实时在线系统,数据同步是关键环节,在相同的网络环境下,数据量决定了同时在线用户量体,数据量也会影响网络延迟和加载时间。所以承载数据的网络带宽是珍贵且昂贵的,所以要在网络数据同步环节细扣每一个 bit !

案例说明

一个用户有16个设备,每个设备有三种状态: 0 未连接,1 连接异常,2 连接正常。需要用最小的数据量来同步这16个设备的连接状态。

1
2
3
4
5
6
enum DeviceState
{
Connected,
Abnormal,
Normal
};

实现思路

每个 bit 有 0 和 1 两种状态,那么至少需要用2个 bit 来表示三种状态,16个设备需要32个 bit。
可以把这8个属性编码到一个 uint32 的整数中,前16位分别表示是否连接,后16位分别表示连接是否正常。

C++实现

这里涉及到整数每个位的操作,我们先在蓝图函数库中写几个位操作的函数,同时暴露给蓝图。

MyBPFLibrary.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include "MyBPFLibrary.generated.h"


// 把 source 第 index 位设置为 1
#define SETBIT(souce, index) souce |= (1 << index)
// 把 source 第 index 位设置为 0
#define CLEARBIT(souce, index) souce &= ~(1 << index)
// 把 source 第 index 位取反
#define REVERSEBIT(souce, index) souce ^= (1 << index)
// 获取 source 第 index 位的值
#define GETBIT(souce, index) ((souce) >> (index) & 1)

/**
*
*/
UCLASS()
class MYPROJECT_API UMyBPFLibrary : public UBlueprintFunctionLibrary
{
GENERATED_BODY()

/**
* 设置一个 int32 的每一个位的值 0 or 1
*
* @param source 输入值
* @param index 第几位
* @param value 要设置的值 0 or 1
* @return 修改后的值
*/
UFUNCTION(BlueprintPure, BlueprintCallable, Category = "Bitwise")
static FORCEINLINE int32 SetBitValue(int32 source, const int32 index, const uint8 value)
{
return value ? SETBIT(source, index) : CLEARBIT(source, index) ;
}


/**
* 获取一个 int32 的某位的值 0 or 1
*
* @param source 输入值
* @param index 第几位
* @return 获取的值 0 or 1
*/
UFUNCTION(BlueprintPure, BlueprintCallable, Category = "Bitwise")
static FORCEINLINE uint8 GetBitValue(const int32 source, const int32 index)
{
return GETBIT(source, index);
}

};

image-20210817233346631

纯蓝图实现

蓝图只支持 int32 的位运算,而且只有四种( 与,或,非,异或)。所以实现起来稍微麻烦一点,执行效率未知。

因为涉及到求2的n次方,所以先写一个求n次方的函数:
image-20210818213329750

默认输入值设置为 2
image-20210818213524122

再写一个获取某一位的值:
image-20210818213651817

然后是设置某一位的值:
image-20210818213727555

总结

以上我们就通过C++ 和 蓝图分别实现了如何对一个整数的每一个位的0/1值进行编码,用来表示和传输一些属性的状态。接收到数据后再根据编码规则获得每个位的值所表示的状态。
设备的状态原来用 uint8 也就是8个 bit来存储,编码后只需要2个bit就可以了,数据量减少了3/4。在同步帧率较高的情况下,效果是显著的。

------------- 感谢您的阅读-------------
作者dreamingpoet
有问题请发邮箱 Dreamingoet@126.com
您的鼓励将成为创作者的动力