1. 레플리케이션(Replication)
- 서버가 게임 상태(state) 데이터를 클라이언트에 보내 동기화하는 과정.
- 진짜 게임 상태는 서버에 존재하며, 클라이언트는 이를 복제하여 그래픽과 사운드를 렌더링.
- 올바르게 설정하면 여러 클라이언트 간의 게임플레이가 원활하게 동기화됨.
1-1. Replication 대상
- 네트워크 동기화는 주로 AActor 및 Actor에서 파생된 클래스에서 이루어짐.
- AActor: 레벨에 배치되거나 동적으로 생성 가능한 기본 클래스이며, UE의 네트워크 지원이 적용된 첫 번째 클래스.
- UObject도 동기화 가능하지만, Replicated Subobject로 Actor에 부착되어야 동작.
1-2. Replication 설정 방법
- C++: bReplicates = true; 설정.
- 블루프린트: Replicates 옵션 활성화.
- bReplicateMovement = true; 설정하면 이동 정보 자동 동기화.
1-3. Replication의 주요 개념/매커니즘
(1). Replicated Properties (속성 동기화)
- 속성 값을 서버에서 클라이언트로 자동 동기화.
- 예시: Health, Ammo 같은 변수.
UPROPERTY(Replicated)
uint32 Health;
(2). Replicated Using Properties (속성 동기화 + 함수 호출)
- 속성이 변경되면 특정 함수를 실행하도록 설정 가능.
- 예시: OnRep_Health()를 설정하면 Health가 바뀔 때 자동 호출.
UPROPERTY(ReplicatedUsing=OnRep_HealthUpdate)
uint32 Health;
UFUNCTION()
void OnRep_HealthUpdate();
(3). Remote Procedure Calls (RPC, 원격 프로시저 호출)
- 한 머신(클라이언트 or 서버)에서 다른 머신에서 실행될 함수를 호출.
- 종류:
- Server RPC: 클라이언트 → 서버에서 실행 (Server_TakeDamage())
- Client RPC: 서버 → 특정 클라이언트에서 실행 (Client_ShowDamageEffect())
- Multicast RPC: 서버 → 모든 클라이언트에서 실행 (Multicast_ExplosionEffect())
UFUNCTION(Server, Reliable, WithValidation)
void ServerDoSomething();
UFUNCTION(Client, UnReliable)
void ClientDoSomething();
UFUNCTION(NetMulticast, Reliable)
void MulticastDoSomething();
2. 액터 레플리케이션(Actor Replication)
2-1. Actor Replication 과정
(1) 클라이언트가 동기화할 Actor 결정
- 동기화할 Actor 목록 작성
- AActor::SetReplicates(true)가 설정된 Actor만 동기화 대상.
- AActor::NetUpdateFrequency를 확인하여 업데이트 빈도 결정.
- AActor::bOnlyRelevantToOwner가 true면 소유자에게만 동기화.
- AActor::PreReplication() 호출하여 특정 속성의 동기화 여부 결정.
- 각 클라이언트별 동기화 대상 선정
- AActor::IsNetRelevantFor()를 호출하여 현재 클라이언트에 대해 Actor가 유효한지 확인.
- AActor::NetDormancy를 확인하여 Actor가 비활성화(Dormant) 상태인지 체크.
- 클라이언트가 Actor가 위치한 레벨을 로드하지 않았다면 동기화하지 않음.
- Actor 동기화 우선순위 정렬
- AActor::GetNetPriority()를 호출하여 우선순위가 높은 Actor부터 동기화.
- 동기화 할 Actor 순회 및 전송
- Actor의 속성이 변경되었는지 확인 후 UActorChannel::ReplicateActor() 호출.
- Actor의 컴포넌트 및 속성 변화를 클라이언트로 전송.
- 만약 5초 이상 Relevancy를 잃으면 채널을 닫음.
- 최적화 옵션
- -limitclientticks 커맨드라인 옵션으로 초당 클라이언트 업데이트 횟수 제한 가능.
- NetClientTicksPerSecond 엔진 설정 변경 가능.
- net.MaxConnectionsToTickPerServerFrame 콘솔 변수로 조정 가능.
(2). 서버가 속성 및 RPC 실행 순서 결정
- 액터 속성(Actor Properties)
- Actor 속성 동기화는 실행 순서 보장X.
- OnRep(RepNotify)도 실행 순서 보장X.
- 순서가 중요한 경우, 여러 변수를 구조체(struct)로 묶어 관리하는 것을 권장.
- 원격 프로시저 호출(RPC)
- Actor 간 실행 순서 보장되지 않음
MyActor->ClientRPC1();
OtherActor->ClientRPC2();
MyActor->ClientRPC3();
//실행 순서
RPC1 → RPC2 → RPC3
RPC2 → RPC3 → RPC1
RPC3 → RPC1 → RPC2
//해결 방법:
순서가 중요한 경우 단일 Actor 내에서만 RPC를 호출하는 것이 좋음.
- 동일 Actor 내 Reliable RPC 실행 순서 보장
MyActor->ClientReliableRPC1();
MyActor->ClientReliableRPC2();
MyActor->ClientReliableRPC3();
//실행 순서
항상 RPC1 → RPC2 → RPC3 순서로 실행
- Actor와 Subobject 간 실행 순서 유지됨
MyActor->RPC1();
MyActor->SubObject1->RPC2();
MyActor->SubObject2->RPC3();
MyActor->RPC4();
//실행 순서
항상 RPC1 → RPC2 → RPC3 → RPC4 순서로 실행.
- Reliable vs Unreliable RPC 실행 순서
MyActor->ClientReliableRPC1();
MyActor->ClientUnreliableRPC2();
MyActor->ClientReliableRPC3();
//실행순서:
Reliable RPC: 실행 순서가 항상 보장됨.
Unreliable RPC: 네트워크 상태에 따라 손실될 수 있음.
네트워크 문제가 없으면: RPC1 → RPC2 → RPC3
RPC2가 유실되면: RPC1 → RPC3 (RPC2 실행되지 않음)
- Multicast vs Unicast RPC
- Reliable Multicast
MyActor->MulticastReliableRPC1();
MyActor->UnicastReliableRPC2();
MyActor->MulticastReliableRPC3();
//실행 순서:
항상 RPC1 → RPC2 → RPC3 순서로 실행
- Unreliable Multicast
MyActor->MulticastUnreliableRPC1();
MyActor->UnicastReliableRPC2();
MyActor->MulticastUnreliableRPC3();
MyActor->UnicastUnreliableRPC4();
//실행 순서:
예시: RPC2 → RPC4 → RPC1 → RPC3
Unreliable Multicast는 항상 마지막에 실행될 가능성이 큼.
- RPC 전송 정책 (Remote Function Send Policy)
- Force Send(): 강제로 바로 전송
MyActor->ForceSendMulticastUnreliableRPC1();
MyActor->UnicastReliableRPC2();
MyActor->MulticastUnreliableRPC3();
MyActor->UnicastUnreliableRPC4();
//실행 순서:
RPC1 → RPC2 → RPC4 → RPC3 (RPC1이 강제로 먼저 실행됨)
void AMyActor::ForceSendToClient()
{
if (HasAuthority())
{
UActorChannel* ActorChannel = GetChannelByActor(GetOwner());
if (ActorChannel)
{
ActorChannel->ForceSend(); // 데이터를 즉시 보내도록 강제
}
}
}
- Force Queue(): 강제로 대기
MyActor->ForceQueueRPC1();
MyActor->UnicastReliableRPC2();
MyActor->MulticastUnreliableRPC3();
MyActor->UnicastUnreliableRPC4();
//실행 순서:
RPC2 → RPC4 → RPC1 → RPC3 (RPC1이 강제로 마지막에 실행됨)
void AMyActor::ForceQueueToSendLater()
{
FQueuedMessage NewMessage;
NewMessage.MessageType = EMessageType::MyCustomMessage;
NewMessage.MessageData = "This is a delayed message.";
// 큐에 넣기 (이 큐는 네트워크 전송을 나중에 할 수 있도록 설정됨)
MessageQueue.Enqueue(NewMessage);
}
- RPC vs 속성 동기화 순서
MyActor->ReliableRPC1();
MyActor->bReplicatedVar1 = true;
MyActor->MulticastUnreliableRPC2();
MyActor->bReplicatedVar2 = true;
MyActor->ReliableRPC3();
//실행 순서:
RPC1 실행
RPC3 실행
bReplicatedVar1, bReplicatedVar2 동기화
RPC2 실행 (Unreliable Multicast는 항상 마지막)
(3). 서버가 클라이언트에 데이터 전송
- 각 클라이언트에 필요한 정보만 전송하여 최적화 수행.
2-2. Replication 주요 기능
기능 | 설명 |
생성 & 삭제 | 서버에서 생성된 레플리케이션 Actor는 클라이언트에서 자동으로 복제됨. 서버에서 삭제되면 클라이언트에서도 삭제됨. |
이동 (Movement Replication) | bReplicateMovement = true 설정 시 위치, 회전, 속도 자동 동기화. |
속성 (Properties) | UPROPERTY(Replicated) 속성은 값이 바뀌면 자동 동기화됨. |
컴포넌트 (Components) | 복제 설정된 컴포넌트와 그 속성, RPC도 복제 가능. |
서브오브젝트 (Subobjects) | UObject도 Actor에 부착하면 복제 가능. |
RPC | 네트워크에서 특정 함수 실행 가능 (Server, Client, Multicast). |
2-3. Replicate 되지 않는 요소들
- Skeletal Mesh Component
- Static Mesh Component
- Materials
- Animation Blueprints
- Particle System Component
- Sound Emitters
- Physics Objects
➜ 개별적으로 실행되지만, 이들을 제어하는 변수를 복제하면 클라이언트 간 동기화 가능.
------------
'TIL > C++와 UE' 카테고리의 다른 글
GameInstanceSubsystem (0) | 2025.04.02 |
---|---|
Object Pooling (0) | 2025.03.28 |
네트워킹 및 멀티 플레이어 개요 (0) | 2025.03.10 |
작성중 (0) | 2025.02.26 |
머티리얼 조작 (0) | 2025.02.25 |