PART 6 · 강의 2/8

Property Replication

변수 복제와 조건부 복제 마스터하기

01

기본 Property 복제

Replicated와 ReplicatedUsing

Property Replication은 서버에서 변경된 변수를 자동으로 클라이언트에 동기화합니다. UPROPERTY 지정자로 복제를 설정합니다.

MyCharacter.h UCLASS() class MYGAME_API AMyCharacter : public ACharacter { GENERATED_BODY() public: AMyCharacter(); // 기본 복제 속성 UPROPERTY(Replicated) int32 CurrentScore; // RepNotify를 사용한 복제 속성 UPROPERTY(ReplicatedUsing = OnRep_Health) float Health; // RepNotify 콜백 함수 UFUNCTION() void OnRep_Health(); // 이전 값을 받는 RepNotify (UE5) UPROPERTY(ReplicatedUsing = OnRep_Armor) float Armor; UFUNCTION() void OnRep_Armor(float PreviousArmor); // 필수: 복제 속성 등록 virtual void GetLifetimeReplicatedProps( TArray<FLifetimeProperty>& OutLifetimeProps) const override; };
MyCharacter.cpp #include "MyCharacter.h" #include "Net/UnrealNetwork.h" AMyCharacter::AMyCharacter() { // 복제 활성화 bReplicates = true; // 이동 복제 SetReplicateMovement(true); Health = 100.0f; Armor = 0.0f; CurrentScore = 0; } void AMyCharacter::GetLifetimeReplicatedProps( TArray<FLifetimeProperty>& OutLifetimeProps) const { Super::GetLifetimeReplicatedProps(OutLifetimeProps); // 기본 복제 DOREPLIFETIME(AMyCharacter, CurrentScore); DOREPLIFETIME(AMyCharacter, Health); DOREPLIFETIME(AMyCharacter, Armor); } void AMyCharacter::OnRep_Health() { // 클라이언트에서 Health가 변경될 때 호출 if (Health <= 0.0f) { PlayDeathAnimation(); } UpdateHealthBar(); } void AMyCharacter::OnRep_Armor(float PreviousArmor) { // 이전 값과 현재 값 비교 가능! float ArmorDelta = Armor - PreviousArmor; if (ArmorDelta > 0) { PlayArmorGainEffect(); } else if (ArmorDelta < 0) { PlayArmorDamageEffect(); } }
02

조건부 복제

DOREPLIFETIME_CONDITION

대역폭을 절약하기 위해 특정 조건에서만 복제하도록 설정할 수 있습니다.

조건 설명 사용 예시
COND_None 모든 클라이언트에 복제 체력, 위치
COND_OwnerOnly 소유자에게만 복제 탄약 수, 인벤토리
COND_SkipOwner 소유자 제외 복제 외형, 장비 시각화
COND_InitialOnly 초기화 시에만 복제 팀 ID, 플레이어 이름
COND_Custom 커스텀 조건 같은 팀만 등
조건부 복제 예제 void AMyCharacter::GetLifetimeReplicatedProps( TArray<FLifetimeProperty>& OutLifetimeProps) const { Super::GetLifetimeReplicatedProps(OutLifetimeProps); // 소유자에게만 복제 (예: 탄약 수) DOREPLIFETIME_CONDITION(AMyCharacter, CurrentAmmo, COND_OwnerOnly); // 소유자 제외 복제 (예: 다른 플레이어가 볼 외형) DOREPLIFETIME_CONDITION(AMyCharacter, CurrentSkin, COND_SkipOwner); // 초기화 시에만 복제 DOREPLIFETIME_CONDITION(AMyCharacter, TeamID, COND_InitialOnly); // 커스텀 조건 복제 DOREPLIFETIME_CONDITION(AMyCharacter, SecretData, COND_Custom); }
03

커스텀 조건 복제

PreReplication과 ACTIVE_OVERRIDE

커스텀 조건 구현 // MyCharacter.h class AMyCharacter : public ACharacter { // ... // PreReplication 오버라이드 virtual void PreReplication( IRepChangedPropertyTracker& ChangedPropertyTracker) override; protected: UPROPERTY(ReplicatedUsing = OnRep_SecretData) FString SecretData; // 같은 팀 여부 bool bSameTeam; }; // MyCharacter.cpp void AMyCharacter::PreReplication( IRepChangedPropertyTracker& ChangedPropertyTracker) { Super::PreReplication(ChangedPropertyTracker); // 복제 대상 클라이언트와 팀 비교 로직 // (실제로는 ViewTarget의 PlayerState에서 팀 정보를 가져옴) // SecretData는 같은 팀에게만 복제 DOREPLIFETIME_ACTIVE_OVERRIDE( AMyCharacter, SecretData, bSameTeam); }

DOREPLIFETIME_ACTIVE_OVERRIDE

PreReplication에서 런타임에 복제 여부를 동적으로 결정합니다. 마지막 파라미터가 true일 때만 복제됩니다.

04

Push Model 복제

성능 최적화를 위한 명시적 더티 마킹

Push Model은 속성이 변경될 때 명시적으로 더티 플래그를 설정하여, 서버가 매 프레임 모든 속성을 비교하지 않아도 되게 합니다.

Push Model 사용 // MyActor.h UPROPERTY(Replicated) int32 ImportantValue; // MyActor.cpp void AMyActor::SetImportantValue(int32 NewValue) { if (ImportantValue != NewValue) { ImportantValue = NewValue; // Push Model: 명시적으로 더티 마킹 MARK_PROPERTY_DIRTY_FROM_NAME( AMyActor, ImportantValue, this); } } // GetLifetimeReplicatedProps에서 Push Model 등록 void AMyActor::GetLifetimeReplicatedProps( TArray<FLifetimeProperty>& OutLifetimeProps) const { Super::GetLifetimeReplicatedProps(OutLifetimeProps); // FDoRepLifetimeParams로 Push Model 설정 FDoRepLifetimeParams Params; Params.bIsPushBased = true; DOREPLIFETIME_WITH_PARAMS_FAST( AMyActor, ImportantValue, Params); }
Push Model 활성화

DefaultEngine.ini에서 전역으로 활성화할 수 있습니다:
[SystemSettings]
net.IsPushModelEnabled=1

SUMMARY

핵심 요약

  • Replicated — 단순 복제, 값 변경 시 자동 동기화
  • ReplicatedUsing — 복제 시 콜백 함수 호출, UI 업데이트 등에 활용
  • DOREPLIFETIME_CONDITION — 조건부 복제로 대역폭 절약
  • COND_OwnerOnly — 소유자에게만 복제, 개인 정보에 사용
  • Push Model — 명시적 더티 마킹으로 성능 최적화
PRACTICE

도전 과제

배운 내용을 직접 실습해보세요

실습 1: 기본 프로퍼티 복제

UPROPERTY(Replicated)로 Health, CurrentWeapon을 선언하고, GetLifetimeReplicatedProps()에서 DOREPLIFETIME을 추가하세요. 서버에서 값을 변경하고 클라이언트에서 동기화되는 것을 확인하세요.

실습 2: ReplicatedUsing으로 변경 콜백

UPROPERTY(ReplicatedUsing=OnRep_Health)를 구현하여 체력 변경 시 클라이언트에서 UI 업데이트와 피격 이펙트를 재생하세요. OnRep 함수에서 이전 값과 새 값을 비교하세요.

심화 과제: 조건부 복제 최적화

DOREPLIFETIME_CONDITION(COND_OwnerOnly)로 소유자에게만 복제되는 프로퍼티(인벤토리)와 COND_SkipOwner로 다른 플레이어에게만 복제되는 프로퍼티(3인칭 애니메이션)를 분리하세요.