UE5 네트워크 직렬화와 Fast TArray
기본 프로퍼티 복제
섹션 제목: “기본 프로퍼티 복제”void AMyActor::GetLifetimeReplicatedProps( TArray<FLifetimeProperty>& OutLifetimeProps) const { Super::GetLifetimeReplicatedProps(OutLifetimeProps);
DOREPLIFETIME(AMyActor, Health); // 조건부 복제 DOREPLIFETIME_CONDITION(AMyActor, TeamColor, COND_InitialOnly); DOREPLIFETIME_CONDITION(AMyActor, bIsVisible, COND_SkipOwner);}커스텀 NetSerialize
섹션 제목: “커스텀 NetSerialize”기본 직렬화보다 적은 비트를 사용해 대역폭을 줄입니다.
USTRUCT()struct FCompressedVector { GENERATED_BODY()
FVector Value;
bool NetSerialize(FArchive& Ar, UPackageMap* Map, bool& bOutSuccess) { // 16비트 고정 소수점으로 압축 (기본 96비트 → 48비트) if (Ar.IsSaving()) { int16 X = FMath::RoundToInt(Value.X * 10.f); int16 Y = FMath::RoundToInt(Value.Y * 10.f); int16 Z = FMath::RoundToInt(Value.Z * 10.f); Ar << X << Y << Z; } else { int16 X, Y, Z; Ar << X << Y << Z; Value = FVector(X * 0.1f, Y * 0.1f, Z * 0.1f); } bOutSuccess = true; return true; }};
template<>struct TStructOpsTypeTraits<FCompressedVector> : TStructOpsTypeTraitsBase2<FCompressedVector> { enum { WithNetSerializer = true };};Fast TArray Replication
섹션 제목: “Fast TArray Replication”일반 TArray 복제는 배열 전체를 비교합니다. FFastArraySerializer는 변경된 항목만 전송합니다.
USTRUCT()struct FInventoryItem : public FFastArraySerializerItem { GENERATED_BODY()
UPROPERTY() int32 ItemId = 0; UPROPERTY() int32 Quantity = 0; UPROPERTY() float Durability = 1.f;
// 클라이언트에서 항목 변경 시 호출 void PostReplicatedChange(const struct FInventoryList& InArraySerializer); void PostReplicatedAdd(const struct FInventoryList& InArraySerializer); void PreReplicatedRemove(const struct FInventoryList& InArraySerializer);};
USTRUCT()struct FInventoryList : public FFastArraySerializer { GENERATED_BODY()
UPROPERTY() TArray<FInventoryItem> Items;
bool NetDeltaSerialize(FNetDeltaSerializeInfo& DeltaParms) { return FFastArraySerializer::FastArrayDeltaSerialize<FInventoryItem, FInventoryList>( Items, DeltaParms, *this); }};
template<>struct TStructOpsTypeTraits<FInventoryList> : TStructOpsTypeTraitsBase2<FInventoryList> { enum { WithNetDeltaSerializer = true };};컴포넌트에서 사용:
UCLASS()class UInventoryComponent : public UActorComponent { GENERATED_BODY()
UPROPERTY(Replicated) FInventoryList Inventory;
void AddItem(int32 ItemId, int32 Qty) { FInventoryItem& NewItem = Inventory.Items.AddDefaulted_GetRef(); NewItem.ItemId = ItemId; NewItem.Quantity = Qty; Inventory.MarkItemDirty(NewItem); // 변경 표시 }
void RemoveItem(int32 Index) { Inventory.Items.RemoveAt(Index); Inventory.MarkArrayDirty(); }};조건부 복제 조건 정리
섹션 제목: “조건부 복제 조건 정리”| 조건 | 설명 |
|---|---|
COND_None | 항상 복제 |
COND_InitialOnly | 첫 복제 시만 |
COND_OwnerOnly | 소유 클라이언트만 |
COND_SkipOwner | 소유 클라이언트 제외 |
COND_SimulatedOnly | 시뮬레이션 프록시만 |
COND_Dynamic | 런타임에 조건 변경 |
대역폭 절약 팁
섹션 제목: “대역폭 절약 팁”// 1. 작은 변화는 복제 안 함UPROPERTY(ReplicatedUsing = OnRep_Health)float Health;
void AMyCharacter::SetHealth(float NewHealth) { if (FMath::Abs(NewHealth - Health) < 0.01f) return; // 작은 변화 무시 Health = NewHealth;}
// 2. 네트워크 업데이트 빈도 조절NetUpdateFrequency = 10.f; // 초당 10회 (기본 100)MinNetUpdateFrequency = 2.f; // 최소 초당 2회NetSerialize로 구조체를 비트 단위로 압축해 대역폭 절약FFastArraySerializer로 대형 배열 변경 시 델타 전송MarkItemDirty/MarkArrayDirty로 변경된 항목만 표시DOREPLIFETIME_CONDITION으로 불필요한 클라이언트에 복제 차단NetUpdateFrequency낮춰 업데이트 빈도 조절