언리얼 네트워크 리플리케이션

민트맛치킨·2025년 10월 24일

Unreal

목록 보기
17/26

리플리케이션

  • 서버와 클라이언트 간 데이터를 자동으로 동기화하는 시스템
  • 멀티플레이어 게임에서 게임 상태를 모든 플레이어에게 일관되게 유지
  • 서버가 정답을 가지고 클라이언트는 복사본을 받는 서버 권한 모델
  • 단방향 복제: 서버 → 클라이언트만 가능 (역방향 불가)

변수 복제 (Property Replication)

class AMyCharacter : public ACharacter
{
    GENERATED_BODY()
    
    // 변수 선언
    UPROPERTY(Replicated)
    float Health;
    
    // 복제 등록
    virtual void GetLifetimeReplicatedProps(
        TArray& OutLifetimeProps) const override
    {
        Super::GetLifetimeReplicatedProps(OutLifetimeProps);
        
        DOREPLIFETIME(AMyCharacter, Health);
    }
};

동작 원리

  • 서버에서 변수 값이 변경되면 자동으로 클라이언트에 전송
  • 값이 실제로 변경될 때만 전송 (같은 값으로 설정해도 네트워크 트래픽 없음)
  • 복제는 일정 주기마다 발생 (NetUpdateFrequency로 조절 가능)

전제 조건

AMyActor()
{
    bReplicates = true;  // 필수
}
  • 액터의 bReplicates가 true여야 변수 복제 동작
  • 서버에서 스폰된 액터만 복제됨 (클라이언트 로컬 스폰은 복제 안됨)

RepNotify (복제 콜백)

class AMyCharacter : public ACharacter
{
    // ReplicatedUsing 지정
    UPROPERTY(ReplicatedUsing=OnRep_Health)
    float Health;
    
    // 콜백 함수
    UFUNCTION()
    void OnRep_Health()
    {
        // 값이 복제될 때마다 호출
        UpdateHealthBar();
        PlayHurtAnimation();
    }
    
    virtual void GetLifetimeReplicatedProps(
        TArray& OutLifetimeProps) const override
    {
        Super::GetLifetimeReplicatedProps(OutLifetimeProps);
        DOREPLIFETIME(AMyCharacter, Health);
    }
};

특징

  • 값이 복제될 때 자동으로 함수 호출
  • UI 업데이트, 비주얼 변경 등에 사용
  • 클라이언트에서만 호출됨 (서버에서는 직접 처리)
  • 함수명은 반드시 OnRep_변수명 형식 권장

복제 조건 (Replication Conditions)

기본 복제 (모두에게)

// 모든 클라이언트에게 복제
DOREPLIFETIME(AMyCharacter, Health);

COND_OwnerOnly (소유자만)

// 소유자(본인)에게만 복제
DOREPLIFETIME_CONDITION(AMyCharacter, Ammo, COND_OwnerOnly);

용도: 탄약, 돈, 개인 인벤토리 등 본인만 알면 되는 정보

COND_SkipOwner (소유자 제외)

// 소유자를 제외한 모든 클라이언트에게 복제
DOREPLIFETIME_CONDITION(AMyCharacter, EquippedWeapon, COND_SkipOwner);

용도: 본인은 이미 아는 정보, 다른 플레이어만 봐야 하는 것

COND_InitialOnly (초기 한 번만)

// 최초 생성 시 한 번만 복제
DOREPLIFETIME_CONDITION(AMyCharacter, MaxHealth, COND_InitialOnly);

용도: 최대 체력, 캐릭터 레벨, 이름 등 불변 데이터

COND_SimulatedOnly (다른 플레이어들만)

// SimulatedProxy에게만 복제
DOREPLIFETIME_CONDITION(AMyCharacter, ReplicatedMovement, COND_SimulatedOnly);

용도: 다른 플레이어들의 보간용 위치 데이터

COND_AutonomousOnly (본인 캐릭터만)

// AutonomousProxy에게만 복제
DOREPLIFETIME_CONDITION(AMyCharacter, ServerPosition, COND_AutonomousOnly);

용도: 본인 캐릭터의 움직임 검증 데이터

복제 조건 전체 목록

COND_None               		// 조건 없음 (기본)
COND_InitialOnly        		// 초기 한 번만
COND_OwnerOnly          		// Owner만
COND_SkipOwner          		// Owner 제외
COND_SimulatedOnly      		// Simulated만
COND_AutonomousOnly     		// Autonomous만
COND_SimulatedOrPhysics 		// Simulated 또는 Physics
COND_InitialOrOwner     		// 초기 또는 Owner
COND_Custom             		// 커스텀 로직
COND_ReplayOrOwner      		// Replay 또는 Owner
COND_ReplayOnly         		// Replay만
COND_SimulatedOnlyNoReplay      // Simulated, Replay 제외
COND_SimulatedOrPhysicsNoReplay // Simulated/Physics, Replay 제외
COND_SkipReplay         		// Replay 제외
COND_Never              		// 절대 복제 안함
조건복제 대상주요 용도
기본 (없음)모든 클라이언트체력, 팀, 점수
COND_OwnerOnly소유자만탄약, 돈, 인벤토리
COND_SkipOwner소유자 제외장착 무기 메시
COND_InitialOnly초기 한 번만최대 체력, 레벨, 이름
COND_SimulatedOnly다른 플레이어들보간용 위치
COND_AutonomousOnly본인 캐릭터서버 위치 검증

RPC (Remote Procedure Call)

Server RPC (클라이언트 → 서버)

class AMyCharacter : public ACharacter
{
    // 선언
    UFUNCTION(Server, Reliable, WithValidation)
    void ServerFire();
    
    // 구현
    void ServerFire_Implementation()
    {
        // 서버에서 실행되는 코드
        SpawnBullet();
        Ammo--;
    }
    
    // 검증 (치트 방지)
    bool ServerFire_Validate()
    {
        // false 반환 시 클라이언트 킥
        return Ammo > 0 && !IsReloading;
    }
};

// 클라이언트에서 호출
void Fire()
{
    ServerFire();  // 서버에 요청
}

특징:

  • 클라이언트가 서버에게 뭔가를 요청할 때 사용
  • 함수명은 Server로 시작 (관례)
  • WithValidation으로 치트 방지 가능

호출 조건 (3가지 모두 필요):
1. bReplicates = true
2. Local Role = AutonomousProxy (본인 캐릭터만)
3. Owner가 설정되어 있어야 함

Client RPC (서버 → 특정 클라이언트)

class APlayerController : public APlayerController
{
    // 선언
    UFUNCTION(Client, Reliable)
    void ClientShowMessage(const FString& Message);
    
    // 구현
    void ClientShowMessage_Implementation(const FString& Message)
    {
        // 해당 클라이언트에서만 실행
        ShowNotification(Message);
    }
};

// 서버에서 호출
void OnKill(APlayerController* Killer)
{
    Killer->ClientShowMessage(TEXT("적 처치!"));
}

특징:

  • 서버가 특정 플레이어에게 개인적인 알림을 보낼 때 사용
  • 함수명은 Client로 시작 (관례)
  • 해당 액터를 소유한 클라이언트에서만 실행

NetMulticast RPC (서버 → 모든 클라이언트)

class AGrenade : public AActor
{
    // 선언
    UFUNCTION(NetMulticast, Unreliable)
    void MulticastPlayExplosion(FVector Location);
    
    // 구현
    void MulticastPlayExplosion_Implementation(FVector Location)
    {
        // 모든 클라이언트 + 서버에서 실행
        SpawnParticle(Location);
        PlaySound(Location);
    }
};

// 서버에서 호출
void Explode()
{
    MulticastPlayExplosion(GetActorLocation());
}

특징:

  • 서버가 모든 클라이언트에게 방송할 때 사용
  • 함수명은 관례적으로 Multicast로 시작
  • 비주얼 이펙트, 사운드 등 모두가 봐야 하는 것에 사용
  • 서버에서도 실행됨
RPC 타입호출 위치실행 위치용도예시
Server클라이언트서버입력, 요청발사, 아이템 획득
Client서버특정 클라개인 알림보상 획득 메시지
NetMulticast서버모든 곳이벤트, 이펙트폭발, 사운드

Reliable vs Unreliable

Reliable (신뢰성 있음)

UFUNCTION(Server, Reliable)
void ServerPickupItem();

UFUNCTION(Client, Reliable)
void ClientShowReward();

특징:

  • 도착 보장: TCP처럼 재전송 메커니즘
  • 순서 보장: 호출 순서대로 실행
  • 느림: 대역폭 많이 사용, 지연 발생 가능
  • 용도: 중요한 게임플레이 로직 (점수, 아이템, 사망 등)

Unreliable (신뢰성 없음)

UFUNCTION(NetMulticast, Unreliable)
void MulticastPlayFootstep();

// 변수 복제도 기본적으로 Unreliable
UPROPERTY(Replicated)
FVector Location;

특징:

  • 유실 가능: UDP처럼 패킷 손실 가능
  • 순서 무관: 뒤바뀔 수 있음
  • 빠름: 대역폭 적게 사용, 지연 적음
  • 용도: 자주 업데이트되는 데이터 (위치, 회전, 이펙트 등)

NetMode와 Role

NetMode (실행 환경)

enum ENetMode
{
    NM_Standalone,        // 싱글플레이
    NM_DedicatedServer,   // 전용 서버
    NM_ListenServer,      // 호스트 서버
    NM_Client            // 클라이언트
};

// 확인
ENetMode Mode = GetNetMode();
bool IsServer = HasAuthority();

Role (권한 수준)

enum ENetRole
{
    ROLE_None,              // 네트워크 없음
    ROLE_SimulatedProxy,    // 다른 플레이어 캐릭터
    ROLE_AutonomousProxy,   // 내 캐릭터
    ROLE_Authority          // 서버
};

// 확인
ENetRole LocalRole = GetLocalRole();
ENetRole RemoteRole = GetRemoteRole();
Role의미권한예시
Authority서버모든 권한서버의 모든 액터
AutonomousProxy내 캐릭터예측 가능본인 조종 캐릭터
SimulatedProxy다른 플레이어받기만다른 플레이어 캐릭터
None복제 안됨로컬만이펙트, 파티클

Local Role vs Remote Role

서버에서 클라이언트A의 캐릭터:

  • Local Role = Authority
  • Remote Role = AutonomousProxy

클라이언트A에서 내 캐릭터:

  • Local Role = AutonomousProxy
  • Remote Role = Authority

클라이언트A에서 클라B의 캐릭터:

  • Local Role = SimulatedProxy
  • Remote Role = Authority

0개의 댓글