언리얼 엔진5 Advanced - 캐릭터 무브먼트의 확장

타입·2025년 4월 8일
0

언리얼 강의

목록 보기
35/47

네트워크 멀티플레이어에서 캐릭터 움직임의 구현

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. CharacterMovementComponent에 텔레포트 명령을 위한 RPC 혹은 프로퍼티 리플리케이션을 새롭게 설계해 추가 구현
  2. CharacterMovementComponent가 사용하는 RPC 기능에 텔레포트 기능을 추가 선언하고, 몇몇 중요한 가상함수를 override하여 구현

1번 방법의 경우 전체적인 CharacterMovementComponent의 설계를 바꿔야 하지만,
2번 방법은 클래스만 교체하는 것으로 간편하게 구현 가능

캐릭터 무브먼트 컴포넌트의 확장

캐릭터 무브먼트 컴포넌트가 관리하는 움직임 정보

  • 캐릭터 무브먼트 구현을 위한 움직임 클래스
    FNetworkPredictionData_Client_Character (클라이언트 캐릭터 데이터)
    FSavedMove_Character (캐릭터 움직임)

  • CharacterMovementComponent의 구현 특징
    CharacterMovementComponent는 클라이언트 캐릭터 데이터의 타입을 확정하지 않음
    클라이언트 캐릭터 데이터 역시 캐릭터 움직임의 타입을 확정하지 않음
    (런타임에 객체를 생성하는 방식)
    따라서 두 클래스를 상속받아 움직임을 추가하는 것이 가능함

  • 움직임 관련 클래스를 바꾸는데 사용되는 가상함수
    • UCharacterMovementComponent::GetPredictionData_Client()
    • FNetworkPredictionData_Client_Character::AllocateNewMove()
    • FNetworkPredictionData_Client_Character::FreeMove()
      커스텀 FSavedMove_Character 클래스에 동적할당이 없다면 FreeMove() 함수는 무시

언리얼 오브젝트의 인자가 있는 생성자 선언

캐릭터 움직임 변경을 위해선 캐릭터에 부착된 CharacterMovementComponent를 커스텀 CharacterMovementComponent로 변경해야함
CharacterMovementComponent는 상위 클래스인 ACharacter에서 이미 생성하기에 원래대로라면 상위 클래스에서 생성한 객체를 제거하고 커스텀 클래스로 할당한 객체로 바꿔줘야함
하지만 언리얼에선 이럴 필요 없이 생성자에서 변경할 수 있도록 기능을 제공함

모든 언리얼 오브젝트는 초기화 오브젝트 인자가 있는 생성자를 사용할 수 있음
FObjectInitializer

초기화 오브젝트 인자를 사용해 서브 오브젝트 클래스를 변경할 수 있음
SetDefaultSubobjectClass< T >()

이를 사용해 새로운 캐릭터 무브먼트 클래스를 생성하지 않고, 우리가 만든 컴포넌트로 교체 가능
언리얼 엔진이 지정한 CharacterMovementComponent의 이름을 사용해 해당 클래스를 찾을 수 있음
ACharacter::CharacterMovementComponentName

클라이언트 캐릭터 데이터의 변경

GetPredictionData_Client() 함수를 오버라이드하여 클래스 변경

캐릭터 움직임의 변경

AllocateNewMove() 함수를 오버라이드하여 클래스 변경

신규 움직임 능력을 추가하는 방법

캐릭터 움직임 클래스에서 관리하는 특별한 움직임에 대한 플래그 정보
플래그 값이 변경되면 움직임 시스템에서는 이를 중요한 움직임으로 간주함
기능 확장을 위해 예비 플래그를 4개 준비해두었음
우리가 추가할 새로운 움직임 기능에 대한 플래그를 할당 - FLAG_Custom

	// Bit masks used by GetCompressedFlags() to encode movement information.
	enum CompressedFlags
	{
		FLAG_JumpPressed	= 0x01,	// Jump pressed
		FLAG_WantsToCrouch	= 0x02,	// Wants to crouch
		FLAG_Reserved_1		= 0x04,	// Reserved for future use
		FLAG_Reserved_2		= 0x08,	// Reserved for future use
		// Remaining bit masks are available for custom flags.
		FLAG_Custom_0		= 0x10,
		FLAG_Custom_1		= 0x20,
		FLAG_Custom_2		= 0x40,
		FLAG_Custom_3		= 0x80,
	};

텔레포트 능력의 추가

3초마다 재생 가능한 텔레포트 움직임을 구현

구현 편의를 위해 텔레포트 입력과 텔레포트 가능 여부를 플래그에 설정 (1개만 사용해도 가능함)

  • FLAG_Custom_0
    텔레포트 명령을 내렸는가
  • FLAG_Custom_1
    현재 쿨타임을 포함해 텔레포트가 진행 중인가

두 개의 플래그 정보를 통해 서버는 클라이언트의 상황을 수시로 전달받을 수 있음

텔레포트 능력의 구현 플로우

텔레포트 입력을 시작으로 다음과 같은 플로우로 클라이언트-서버 움직임을 동기화

PerformMovement()에서 캐릭터의 움직임 진행
PerformMovement() 함수는 매우 복잡하기에 이를 직접 오버라이드 하는 대신 OnMovementUpdated() 함수를 오버라이드

실습코드

https://github.com/dnjfs/ArenaBattle_Network/commit/6060e6e44710a7a0194f7f77bd74a644b1bd1b1f

  • 텔레포트 입력 추가
    InputAction 추가
    Input Mapping Context에 연결
    T 버튼 입력 시 텔레포트 입력 발생

  • 커스텀 CharacterMovementComponent 구현
    ABCharacterMovementComponent 클래스 추가
    플레이어 캐릭터의 생성자에서 해당 클래스를 사용하도록 구현
    커스텀 클라이언트 캐릭터 데이터, 캐릭터 움직임 클래스 구현
    클라이언트의 입력에 대한 데이터를 서버에서 받아 클라이언트에서도 텔레포트가 되도록 처리

profile
주니어 언리얼 프로그래머

0개의 댓글