본문 바로가기

Unreal

UE 캐릭터 컨트롤 설정

 

캐릭터 컨트롤

  • 일반적으로 컨트롤러와 폰, 카메라, 스프링암, 캐릭터 무브먼트의 다섯 가지 요소를 사용해 설정
  • 컨트롤러 : 입력자의 의지(목표 지점)을 지정할 때 사용, ControlRotation 속성
  • 폰 : 폰의 트랜스폼을 지정
  • 카메라 : 화면 구도를 설정하기 사용, 주로 1인칭 시점에서 사용
  • 스프링 암 : 화면 구도를 설정하기 위해 사용, 주로 3인칭 시점에서 사용
  • 캐릭터 무브먼트 : 캐릭터의 이동과 회전을 조정하는 용도로 사용.
  • Desired Rotation(최종 목표, 의지), Rotation(현재 회전된 상태)
    • Desired Rotation을 설정하고 Rotation Rate의 각속도로 회전하도록 설정하는 것이 부드러운 움직임을 줌.

 

폰의 컨트롤 옵션

  • Use Controller Rotation (Yaw / Roll /Pitch)
  • 컨트롤러에 지정된 Control Rotation 값에 폰의 Rotation을 맞출 것인지?
  • 이 옵션을 켜면 폰의 회전은 컨트롤러의 Control Rotation 과 동기화됨.

 

스프링 암의 컨트롤 옵션

  • Use Pawn Control Rotation
  • Inherit (Yaw / Roll / Pitch)
  • Do Collision Test
  • 폰의 컨트롤 회전 ( 컨트롤러의 Control Rotation ) 을 사용할 것인지.?
  • 부모 컴포넌트 ( 주로 RootComponent )의 회전을 그대로 따를 것인지?
  • 스프링암 중간에 장애물이 있으면 앞으로 당길 것인가? ( Camera 라는 트레이스 채널 사용)
    • 장애물이 있으면 장애물 앞으로 카메라를 당겨줌
  • 3인칭 시점 설정에 주로 사용.

 

 

캐릭터 무브먼트의 이동 옵션

  • Movement Mode : None, Walking, Falling
  • 땅(Ground)위에 있으면 Walking 모드
  • 땅 위에 없으면 Falling 모드
  • 이동 기능을 끄고 싶으면 None 모드
  • 이동 모드에서의 이동 수치 : MaxWalkSpeed
  • 폴링 모드에서의 점프 수치 : JumpZVelocity

 

 

캐릭터 무브먼트의 회전 옵션

  • Rotation Rate : 회전 속도의 지정
  • Use Controller Desired Rotation : 컨트롤 회전을 목표 회전으로 삼고 지정한 속도로 돌리기
  • Orient Rotation To Movement : 캐릭터 이동 방향에 회전 일치시키기
  • 폰의 회전 옵션과 충돌이 나지 않도록 주의

 

데이터 애셋

  • UDataAsset을 상속받은 언리얼 오브젝트 클래스
  • 에디터에서 애셋 형태로 편리하게 데이터를 관리할 수 있음
  • 캐릭터 컨트롤에 관련된 주요 옵션을 모아 애셋으로 관리

 

데이터 애셋의 관리

  • 두 가지의 컨트롤 모드를 제공
    • 현재 구현된 컨트롤 모드 : 3인칭 솔더뷰
    • 추가로 구현할 컨틀로 모드 : 3인칭 쿼터뷰
  • 입력키 V를 통해 컨트롤 설정을 변경
  • Enum을 통해 두 개의 컨트롤 데이터를 관리

 

데이터 애셋의 구성과 적용

  • 각 섹션별로 데이터를 저장
    • Pawn 카테고리
    • 캐릭터무브먼트 카테고리
    • 입력 카테고리
    • 스프링암 카테고리
  • Pawn과 캐릭터무브먼트 데이터는 CharacterBase에서 설정
  • 입력과 스프링암 데이터는 CharacterPlayer에서 설정

 

IA_ChangeControl

V키를 눌렀을 시 View 전환을 수행하는 블루프린트 객체입니다.

 

 

1. 타입에 따른 Control 변경.

void AABCharacterPlayer::ChangeCharacterControl()
{
	if (CurrentCharacterControlType == ECharacterControlType::Quater)
	{
		SetCharacterControl(ECharacterControlType::Shoulder);
	}
	else if (CurrentCharacterControlType == ECharacterControlType::Shoulder)
	{
		SetCharacterControl(ECharacterControlType::Quater);
	}
}
숄더 뷰, 쿼터 뷰 변경

 

 

2. Control 변경함수.

void AABCharacterPlayer::SetCharacterControl(ECharacterControlType NewCharacterControlType)
{
	UABCharacterControlData* NewCharacterControl = CharacterControlManager[NewCharacterControlType];
	check(NewCharacterControl);

	SetChracterControlData(NewCharacterControl);

	APlayerController* PlayerController = CastChecked<APlayerController>(GetController());
	if (UEnhancedInputLocalPlayerSubsystem* Subsystem = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(PlayerController->GetLocalPlayer()))
	{
		Subsystem->ClearAllMappings();
		UInputMappingContext* NewMappingContext = NewCharacterControl->InputMappingContext;
		if (NewMappingContext)
		{
			Subsystem->AddMappingContext(NewMappingContext, 0);
		}
	}

	CurrentCharacterControlType = NewCharacterControlType;
}
캐릭터 제어 유형을 변경하고 이에 따라 카메라와 입력 매핑을 업데이트하는 역할을 합니다

 

 

3. Character의 컨트롤 데이터 설정

void AABCharacterPlayer::SetChracterControlData(const UABCharacterControlData* CharacterControlData)
{
	Super::SetChracterControlData(CharacterControlData);

	// Camera Spring Arm 설정
	CameraBoom->TargetArmLength = CharacterControlData->TargetArmLength;
	CameraBoom->SetRelativeRotation(CharacterControlData->RelativeRotation);
	CameraBoom->bUsePawnControlRotation = CharacterControlData->bUsePawnControlRotation;
	CameraBoom->bInheritPitch = CharacterControlData->bInheritPitch;
	CameraBoom->bInheritYaw = CharacterControlData->bInheritYaw;
	CameraBoom->bInheritRoll = CharacterControlData->bInheritRoll;
	CameraBoom->bDoCollisionTest = CharacterControlData->bDoCollisionTest;
}
캐릭터의 제어 데이터를 받아와 카메라의 속성을 설정하는 역할을 수행합니다. (Spring Arm)

 

IA_QuaterMove

QuaterVIew일 때 이동을 관장하는 객체

 

 

1. 쿼터 뷰 이동 함수

void AABCharacterPlayer::QuaterMove(const FInputActionValue& Value)
{
	FVector2D MovementVector = Value.Get<FVector2D>();

	float InputSizeSquared = MovementVector.SquaredLength();
	float MovementVectorSize = 1.0f;
	float MovementVectorSizeSquared = MovementVector.SquaredLength();
	if (MovementVectorSizeSquared > 1.0f)
	{
		MovementVector.Normalize();
		MovementVectorSizeSquared = 1.0f;
	}
	else
	{
		MovementVectorSize = FMath::Sqrt(MovementVectorSizeSquared);
	}

	FVector MoveDirection = FVector(MovementVector.X, MovementVector.Y, 0.0f);
	GetController()->SetControlRotation(FRotationMatrix::MakeFromX(MoveDirection).Rotator());
	AddMovementInput(MoveDirection, MovementVectorSize);
}

 

코드는 쿼터뷰에서의 캐릭터 이동을 처리하는 함수
쿼터뷰는 카메라가 캐릭터 뒤쪽 약간 위에서 바라보는 시점.

 

IA_ShoulderLook

ShoulderView일 때 시점을 관장하는 객체

 

 

IA_ShoulderMove

ShoulderView 일 때 이동을 관장하는 객체

 

 

1. 숄더 뷰 이동 함수

void AABCharacterPlayer::ShoulderMove(const FInputActionValue& Value)
{
	FVector2D MovementVector = Value.Get<FVector2D>();

	const FRotator Rotation = Controller->GetControlRotation();
	const FRotator YawRotation(0, Rotation.Yaw, 0);

	const FVector ForwardDirection = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::X);
	const FVector RightDirection = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::Y);

	AddMovementInput(ForwardDirection, MovementVector.X);
	AddMovementInput(RightDirection, MovementVector.Y);
}

 

어깨 시점에서의 캐릭터 이동을 처리하는 함수
어깨 시점이란 카메라가 캐릭터의 어깨 뒤쪽에서 약간 옆으로 바라보는 시점

 

ABCharacterPlayer Input

ABCharacterPlayer의 Input에 설정된 객체들.

 

 

캐릭터와 IA 객체 연결

// header
protected:
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Input, Meta = (AllowPrivateAccess = "true"))
	TObjectPtr<class UInputAction> JumpAction;

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Input, Meta = (AllowPrivateAccess = "true"))
	TObjectPtr<class UInputAction> ChangeControlAction;

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Input, Meta = (AllowPrivateAccess = "true"))
	TObjectPtr<class UInputAction> ShoulderMoveAction;

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Input, Meta = (AllowPrivateAccess = "true"))
	TObjectPtr<class UInputAction> ShoulderLookAction;

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Input, Meta = (AllowPrivateAccess = "true"))
	TObjectPtr<class UInputAction> QuaterMoveAction;
	//... 생략
	
// cpp 생성자

AABCharacterPlayer::AABCharacterPlayer()
{
	// Camera
	//... 생략
    
	// Input
	static ConstructorHelpers::FObjectFinder<UInputAction> InputActionJumpRef(TEXT("/Script/EnhancedInput.InputAction'/Game/ArenaBattle/Input/Actions/IA_Jump.IA_Jump'"));
	if (nullptr != InputActionJumpRef.Object)
	{
		JumpAction = InputActionJumpRef.Object;
	}

	static ConstructorHelpers::FObjectFinder<UInputAction> InputChangeActionControlRef(TEXT("/Script/EnhancedInput.InputAction'/Game/ArenaBattle/Input/Actions/IA_ChangeControl.IA_ChangeControl'"));
	if (nullptr != InputChangeActionControlRef.Object)
	{
		ChangeControlAction = InputChangeActionControlRef.Object;
	}

	static ConstructorHelpers::FObjectFinder<UInputAction> InputActionShoulderMoveRef(TEXT("/Script/EnhancedInput.InputAction'/Game/ArenaBattle/Input/Actions/IA_ShoulderMove.IA_ShoulderMove'"));
	if (nullptr != InputActionShoulderMoveRef.Object)
	{
		ShoulderMoveAction = InputActionShoulderMoveRef.Object;
	}

	static ConstructorHelpers::FObjectFinder<UInputAction> InputActionShoulderLookRef(TEXT("/Script/EnhancedInput.InputAction'/Game/ArenaBattle/Input/Actions/IA_ShoulderLook.IA_ShoulderLook'"));
	if (nullptr != InputActionShoulderLookRef.Object)
	{
		ShoulderLookAction = InputActionShoulderLookRef.Object;
	}

	static ConstructorHelpers::FObjectFinder<UInputAction> InputActionQuaterMoveRef(TEXT("/Script/EnhancedInput.InputAction'/Game/ArenaBattle/Input/Actions/IA_QuaterMove.IA_QuaterMove'"));
	if (nullptr != InputActionQuaterMoveRef.Object)
	{
		QuaterMoveAction = InputActionQuaterMoveRef.Object;
	}

	CurrentCharacterControlType = ECharacterControlType::Quater;

}
게임에서 정의된 다섯 가지 입력 액션을 연결하는 역할

 

Data Asset 연결.

static ConstructorHelpers::FObjectFinder<UABCharacterControlData> ShoulderDataRef(TEXT("/Script/ArenaBattle.ABCharacterControlData'/Game/ArenaBattle/CharacterControl/ABC_Shoulder.ABC_Shoulder'"));
if (ShoulderDataRef.Object)
{
	CharacterControlManager.Add(ECharacterControlType::Shoulder, ShoulderDataRef.Object);
}


static ConstructorHelpers::FObjectFinder<UABCharacterControlData> QuaterDataRef(TEXT("/Script/ArenaBattle.ABCharacterControlData'/Game/ArenaBattle/CharacterControl/ABC_Quater.ABC_Quater'"));
if (QuaterDataRef.Object)
{
	CharacterControlManager.Add(ECharacterControlType::Quater, QuaterDataRef.Object);
}
데이터 애셋을 캐릭터 컨트롤에 연결

 

 

참조

 

이득우의 언리얼 프로그래밍 Part2 - 언리얼 게임 프레임웍의 이해 강의 | 이득우 - 인프런

이득우 | 대기업 현업자들이 수강하는 언리얼 C++ 프로그래밍 전문 과정입니다. 언리얼 C++ 프로그래밍을 사용해 핵&슬래시 로그라이크 게임 예제를 처음부터 끝까지 체계적으로 제작하는 방법을

www.inflearn.com

 

'Unreal' 카테고리의 다른 글

UE - 프로젝트 프로토 타입 - 슈팅 프로젝트(총알 생성 및 적 제작)  (0) 2024.08.24
UE 에디터 - White Boxing  (0) 2024.08.10
UE C++ 리플렉션  (0) 2024.06.22
UE 캐릭터 입력 시스템  (0) 2024.06.15
UE 액터 컴포넌트  (1) 2024.06.08