콘텐츠로 이동

UE5 네트워크 리플리케이션

Unreal Engine의 네트워크 모델은 서버 권위(Server Authoritative) 구조입니다. 서버가 게임 상태를 결정하고 클라이언트에 변경 사항을 전파(Replicate)합니다.


Server (Authority)
├─ 게임 로직 실행
├─ 상태 변경 → 클라이언트로 리플리케이션
└─ RPC 검증 및 처리
Client
├─ 입력 전송 (Server RPC)
├─ 리플리케이션 수신
└─ 예측(Prediction) 및 보정

AMyActor::AMyActor()
{
// Actor 자체를 네트워크상에서 복제
bReplicates = true;
// 이동(Transform)도 리플리케이션
SetReplicatingMovement(true);
}

UPROPERTY(Replicated) 또는 UPROPERTY(ReplicatedUsing=OnRep_함수명) 으로 선언합니다.

UCLASS()
class AMyCharacter : public ACharacter
{
GENERATED_BODY()
public:
// 단순 리플리케이션 (값만 동기화)
UPROPERTY(Replicated)
int32 Health;
// 변경 시 콜백 호출 (ReplicatedUsing)
UPROPERTY(ReplicatedUsing=OnRep_Ammo)
int32 Ammo;
UFUNCTION()
void OnRep_Ammo(int32 OldAmmo);
// GetLifetimeReplicatedProps에 등록 필수
virtual void GetLifetimeReplicatedProps(
TArray<FLifetimeProperty>& OutLifetimeProps) const override;
};
.cpp
void AMyCharacter::GetLifetimeReplicatedProps(
TArray<FLifetimeProperty>& OutLifetimeProps) const
{
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
DOREPLIFETIME(AMyCharacter, Health);
// 조건부 리플리케이션 — 자신의 클라이언트에만 전송
DOREPLIFETIME_CONDITION(AMyCharacter, Ammo, COND_OwnerOnly);
}
void AMyCharacter::OnRep_Ammo(int32 OldAmmo)
{
// 클라이언트에서만 실행 — UI 업데이트 등
UpdateAmmoUI(Ammo);
}
조건설명
COND_None모든 클라이언트
COND_OwnerOnly소유 클라이언트만
COND_SkipOwner소유 클라이언트 제외
COND_InitialOnly첫 리플리케이션만
COND_SimulatedOnly시뮬레이션 프록시만

타입선언실행 위치호출 위치
ServerUFUNCTION(Server, Reliable)서버클라이언트
ClientUFUNCTION(Client, Reliable)소유 클라이언트서버
NetMulticastUFUNCTION(NetMulticast, Unreliable)서버+모든 클라이언트서버
// 헤더
UFUNCTION(Server, Reliable, WithValidation)
void ServerFire(FVector Origin, FVector Direction);
UFUNCTION(NetMulticast, Unreliable)
void MulticastPlayFireEffect();
// .cpp — 구현 시 _Implementation, _Validate 접미사
void AMyCharacter::ServerFire_Implementation(FVector Origin, FVector Direction)
{
// 서버에서만 실행 — 데미지 처리 등
SpawnProjectile(Origin, Direction);
MulticastPlayFireEffect(); // 모든 클라이언트에 이펙트 전송
}
bool AMyCharacter::ServerFire_Validate(FVector Origin, FVector Direction)
{
// 치팅 검증 — false 반환 시 연결 끊김
return Direction.IsNormalized();
}
void AMyCharacter::MulticastPlayFireEffect_Implementation()
{
// 서버+모든 클라이언트 실행 — 사운드·파티클
PlayFireSound();
SpawnMuzzleFlash();
}

void AMyActor::Tick(float DeltaTime)
{
switch (GetLocalRole())
{
case ROLE_Authority:
// 서버 — 게임 로직
break;
case ROLE_AutonomousProxy:
// 소유 클라이언트 — 입력 처리, 예측
break;
case ROLE_SimulatedProxy:
// 비소유 클라이언트 — 보간·시각적 표현
break;
}
}
// 서버 여부만 빠르게 확인
if (HasAuthority()) { /* 서버 전용 코드 */ }

AMyActor::AMyActor()
{
MyComponent = CreateDefaultSubobject<UMyComponent>(TEXT("MyComp"));
MyComponent->SetIsReplicated(true); // 컴포넌트 리플리케이션 활성화
}

  • Reliable RPC 남용 금지 — 보장 전송이라 패킷 손실 시 재전송 → 지연 증가. 파티클·사운드 이펙트는 Unreliable 사용
  • OnRep 함수는 클라이언트에서만 호출 — 서버에서는 호출되지 않으므로 서버 로직을 OnRep에 넣지 말 것
  • RPC는 리플리케이트된 Actor에서만 동작bReplicates = false이면 RPC 전송 안 됨

네트워크 관련성 (Net Relevancy) 최적화

섹션 제목: “네트워크 관련성 (Net Relevancy) 최적화”

모든 Actor를 모든 클라이언트에 복제하면 대역폭이 낭비됩니다. NetCullDistanceSquared로 복제 범위를 제한하고, IsNetRelevantFor로 커스텀 조건을 추가합니다.

AMyPickup::AMyPickup()
{
bReplicates = true;
// 반경 3000cm(30m) 이내 플레이어에게만 복제
NetCullDistanceSquared = 3000.f * 3000.f;
}
// 커스텀 관련성 — 중요 아이템은 거리 무관하게 항상 복제
virtual bool IsNetRelevantFor(
const AActor* RealViewer,
const AActor* ViewTarget,
const FVector& SrcLocation) const override
{
if (bIsImportantItem) return true;
return Super::IsNetRelevantFor(RealViewer, ViewTarget, SrcLocation);
}
void AMyCharacter::GetLifetimeReplicatedProps(
TArray<FLifetimeProperty>& OutLifetimeProps) const
{
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
// 모든 클라이언트
DOREPLIFETIME(AMyCharacter, Health);
// 소유 클라이언트만 (개인 정보: 탄약, 스태미나)
DOREPLIFETIME_CONDITION(AMyCharacter, Ammo, COND_OwnerOnly);
// 초기 1회만 (변하지 않는 캐릭터 타입)
DOREPLIFETIME_CONDITION(AMyCharacter, CharacterClass, COND_InitialOnly);
// 소유 클라이언트 제외 (다른 플레이어의 체력바 표시용)
DOREPLIFETIME_CONDITION(AMyCharacter, TeamID, COND_SkipOwner);
}
조건설명
COND_None모든 클라이언트
COND_OwnerOnly소유 클라이언트만
COND_SkipOwner소유 클라이언트 제외
COND_InitialOnly첫 복제만
COND_SimulatedOnly시뮬레이션 프록시만