캐릭터 Movement 리플리케이션
캐릭터 movement 리플리케이션 플로우
TickComponent에서 가속도를 계산하여 PerformMovement 함수를 호출해서 이동 계산
Autonomous Proxy 클라이언트의 UCharacterMovementComponent::ReplicateToServer
클라이언트 캐릭터의 움직임을 보관하는 네트워크용 클라이언트 데이터 FNetworkPredictionData_Client_Character 생성
클라이언트의 데이터에 저장된 움직임 중에 참고할 중요한 Move 기록(OldMove)
현재 틱의 Move를 기록하는 신규 Move 생성(NewMove)하여 각종 상태를 저장
필요 시 최종 Move와 현재 Move를 병합 시도
클라이언트 로컬에서의 move 진행(PerformMovement)
신규 Move에 Move 결과 상태를 저장하고 클라이언트 데이터에 추가
OldMove와 NewMove를 서버에 전송
ReplicateToServer -> ServerMovePacked -> ClientMoveResponsePacked(조정)
Movement 리플리케이션 디버깅
RPC 패킷을 로그로 확인
// DefaultEngine.ini
[Core.Log]
LogNetPlayerMovement=VeryVerbose
드로우 디버그를 위해 콘솔 변수 p.NetShowCorrection 1 설정
오차 발생시 클라이언트의 위치를 붉은색, 서버의 위치를 녹색으로 표시하고, 수정 후 동일하다면 노란색으로 표시
먼저 보낸 RPC가 이후에 보낸 RPC 혹은 리플리케이션보다 느릴 수 있음
각 채널은 독립적으로 패킷을 처리하므로 순서가 보장되지 않음
액터 Movement 리플리케이션 플로우
액터의 리플리케이션 및 무브먼트 리플리케이션 옵션이 설정돼야 무브먼트 리플리케이션이 실행됨
ReplicatedMovement
서버에서 SimulatedProxy로 보내는 움직임 정보를 기록한 멤버 변수
일반 Movement와 물리 Movement의 리플리케이션을 모두 처리하는 용도로 활용
GatherCurrentMovement
현재 액터의 Movement를 ReplicatedMovement로 변환해 설정하는 함수
액터의 PreReplication 함수에서 호출되어 각 클라이언트에 패킷을 보내기 전에 자신의 상태 데이터를 확정
액터의 물리 무브먼트와 일반 무브먼트를 구분해 각각 처리
일반 무브먼트는 단순히 액터의 위치, 회전, 속도 값을 ReplicatedMovement에 저장
물리 시뮬레이션의 경우 현재 월드에 설정된 물리 씬에서 해당 컴포넌트의 물리 상태를 저장하고 최종 ReplicatedMovement가 설정되어 클라이언트에 보내짐
OnRep_ReplicatedMovement
일반 무브먼트는 Simulated Proxy에 한해서 컴포넌트의 위치와 회전 정보를 갱신, 속도 처리는 별도로 진행하지 않음
물리 무브먼트는 물리 리플리케이션 씬에서 컴포넌트와 일치하는 타겟을 찾아서 업데이트
ApplyRigidBodyState
물리 리플리케이션의 틱에서 호출되는 함수
클라이언트의 물리 상태가 서버의 물리 상태의 오차 내에 있을 때까지 계속 호출됨
서버에서 받은 최종 속도와 핑을 기반으로 클라이언트의 물리 상태를 외삽(다른 변수와의 관계를 통해 추정하는 과정, Extrapolation)으로 예측
예측한 위치와 방향이 서버와 비교하고 문제가 있다면 에러 시간을 누적
누적된 에러 시간 설정값을 넘으면 강제 조정(하드 스냅)을 진행
차이가 크지 않다면 내삽(보간, Interpolation)을 수행해 현재 위치, 회전, 속도, 각속도를 조정
SimulatedPhysics 옵션으로 물리 무브먼트를 활성화
탈 것, 혹은 플랫폼 위에 타는 경우라면 ReplicatedBasedMovement를 활성화해야 함
SimulatedTick
Simulated Proxy 캐릭터가 처리하는 무브먼트
캐릭터만의 추가적인 작업으로, 시뮬레이션으로 캡슐을 이동시킨 후 메시의 무브먼트를 부드럽게 보간(SimulateMovement, SmoothClientPosition)
네트워크 캐릭터 무브먼트 컴포넌트
텔레포트 구현하는 방법
1. 클라이언트에서만 실행 : 네트워크 동기화 X
2. 서버만 RPC : 지연 시간이 눈에 띄고, 순간적인 위치 이동이 아니라 부드러운 이동이 됨
3. 서버 RPC 및 로컬 트리거 : RPC 순서가 바뀌거나 손실이 되면 동기화가 비정상적
4. 캐릭터 무브먼트 컴포넌트 능력 구현 : 캐릭터 무브먼트에 대해 이해하고 텔레포트에 대한 데이터 패킹과 언패킹을 잘 해줘야 함
캐릭터 무브먼트 구현을 위한 무브먼트 클래스
FNetworkPredictionData_Client_Character : 클라이언트 캐릭터 데이터
FSavedMove_Client : 캐릭터 무브먼트
캐릭터 무브먼트 컴포넌트는 클라이언트 캐릭터 데이터의 타입과 캐릭터 무브먼트의 타입을 확정하지 않고 런타임에 객체를 생성하므로 위 두 클래스를 상속받으면 대체 가능
무브먼트 관련 클래스를 바꾸는데 사용되는 가상 함수
UCharcterMovementComponent::GetPredictionData_Client
FNetworkPredictionData_Client_Character::ClientCharacter
FNetworkPredictionData_Client_Character::FreeMove
(만약 동적 할당이 없다면 FreeMove는 무시 가능)
FObjectInitializer를 통해 서브 오브젝트 클래스를 변경할 수 있음
따라서 새로운 캐릭터 무브먼트 컴포넌트로 교체 가능
APNCharacter::APNCharacter(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer.SetDefaultSubobjectClass<UPNCharacterMovementComponent>(ACharacter::CharacterMovementComponentName))
신규 무브먼트 능력을 추가하는 방법
특별한 무브먼트에 대한 플래그 정보인 CompressedFlags를 새로 할당해서 사용
텔레포트 능력 구현 플로우
'언리얼 > 네트워크 멀티플레이 프레임워크' 카테고리의 다른 글
[Unreal Engine5] 서버-클라이언트 구조에서 GameplayAbilitySystem을 사용하는 컴포넌트 초기화 문제 (0) | 2025.04.10 |
---|---|
언리얼5 네트워크 멀티플레이 최적화 (0) | 2025.01.22 |
언리얼5 RPC (0) | 2025.01.13 |
언리얼5 액터 리플리케이션 (0) | 2025.01.10 |
언리얼5 액터의 역할과 Connection HandShaking (0) | 2025.01.08 |