캐릭터 Movement 리플리케이션

캐릭터 movement 리플리케이션 플로우

https://dev.epicgames.com/documentation/en-us/unreal-engine/understanding-networked-movement-in-the-character-movement-component-for-unreal-engine?application_version=5.1\

 

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)

 

네트워크 캐릭터 무브먼트 컴포넌트

https://dev.epicgames.com/documentation/ko-kr/unreal-engine/understanding-networked-movement-in-the-character-movement-component-for-unreal-engine?application_version=5.1

 

텔레포트 구현하는 방법

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를 새로 할당해서 사용

 

텔레포트 능력 구현 플로우

+ Recent posts

목차