跳至主要內容

NT-2.4|网络优化|结构体

Mr.Si大约 2 分钟unreal

本章概要

以方向为例,优化方向结构体的网络传输

问题

头像
先来看个枚举
UENUM(BlueprintType)
enum class EDirectionType : uint8
{
	Forward UMETA(DisplayName = "Forward"),
	Backward UMETA(DisplayName = "Backward"),
	Left UMETA(DisplayName = "Left"),
	Right UMETA(DisplayName = "Right"),
	Invalid UMETA(DisplayName = "Invalid")
};
头像
先来扫个盲

数据单位

1 Byte = 8 Bits 字节(Byte)和位(Bit)是计算机科学和信息技术中使用的数据单位。它们用于衡量数据的大小和存储容量。

头像
思考一下传输这个枚举需要多少数据?
头像
uint8 = 1 Byte = 8 Bits ,传输这个枚举需要1个字节
头像
很好,如果把这个枚举放入结构体中。你认为需要多少字节?
头像
这取决于结构体中有多少成员变量
头像
回到我们的设计的EDirectionType,从设计上来说,你认为需要传输多少位?
头像

1位 可以表示两种状态,0 和 1 2位 可以表示四种状态,0,1,2,3 3位 可以表示八种状态,0,1,2,3,4,5,6,7

  • 000 - 无效
  • 001 - 前
  • 010 - 后
  • 011 - 左
  • 100 - 右
  • 101 - 其他(如果有的话)

UStruct网络同步

/ 自定义结构用于传递简单的枚举值
USTRUCT(BlueprintType)
struct FGameplayAbilityTargetData_SimpleEnum : public FGameplayAbilityTargetData
{
	GENERATED_USTRUCT_BODY()

	// 用于存储简单的枚举值 (例如方向类型)
	UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = Targeting)
	uint8 EnumValue;
	
	virtual UScriptStruct* GetScriptStruct() const override{return FGameplayAbilityTargetData_SimpleEnum::StaticStruct();}

	virtual FString ToString() const override{return FString::Printf(TEXT("EnumValue: %d"), EnumValue);}

	bool NetSerialize(FArchive& Ar, UPackageMap* Map, bool& bOutSuccess)
	{
		//Ar << EnumValue; 8位
		//5个方向,只需3位
		Ar.SerializeBits(&EnumValue,3);
		bOutSuccess = true;
		return true;
	}
};

// 使结构可以通过网络序列化
template<>
struct TStructOpsTypeTraits<FGameplayAbilityTargetData_SimpleEnum> : public TStructOpsTypeTraitsBase2<FGameplayAbilityTargetData_SimpleEnum>
{
	enum
	{
		WithNetSerializer = true,
	};
};