본문 바로가기

게임 개발/이득우의 언리얼 C++

[이득우의 언리얼 C++ 게임개발의 정석] #6. 캐릭터의 제작과 컨트롤

반응형

이득우의-언리얼-C++-게임개발의-정석-표지

인간형 캐릭터를 효과적으로 제작하기 위해 
언리얼 엔진이 제공하는 캐릭터 모델을 학습하고,

이를 기반으로 움직이는 캐릭터를 제작한다.

카메라를 자유자재로 설정하기 위해 컨트롤 회전에 대한 개념을 익힌다.

<1>. 캐릭터 모델

캐릭터 에셋을 사용해 인간형 '폰'을 만들 수도 있지만, '캐릭터' 모델을 사용해서 만들 수도 있다.

 

'ABCharacter" 클래스 생성

→ACharacter라는 클래스 상속받고 있음

→ACharacter는 APawn 클래스를 상속받고 있음

→둘 다 동일하게 Capsule 컴포넌트, SkeletalMesh 컴포넌트, CharacterMovement 컴포넌트를 사용함

 

ACharacter 클래스는 GetCapsuleComponent, GetMesh, GetCharacterMovement 함수를 제공한다. 이를 기반으로 전에 제작한 폰과 동일한 액터를 제작한다   ABCharacter를 DefaultPawn으로 설정한다.

 

<2>. 컨트롤 회전의 활용

플레이어 컨트롤러가 제공하는 속성인 '컨트롤 회전'은 곧 플레이어의 의지를 나타낸다.
→ 입력 설정에서 마우스를 이용해 회전하는 Turn(Z 축 회전), LookUp(Y축 회전) 함수를 사용한다.

→ 캐릭터 모델은 기본으로 '컨트롤 회전의 Yaw 회전' 값과 '폰의 Yaw 회전'이 서로 연동돼 있다.

→ 마우스를 돌렸을 때, 좌우 회전은 하지만 상하회전은 하지 않는다.

//ABCharacter.cpp

void AABCharacter::LookUp(float NewAxisValue)
{
	AddControllerPitchInput(NewAxisValue);
}

void AABCharacter::Turn(float NewAxisValue)
{
	AddControllerYawInput(NewAxisValue);
}

 

<3>. 삼인칭 컨트롤 구현(GTA 방식) - 흰색 마네킹과 동일한 방식

흰색 마네킹은 다음과 같은 성질을 가지고 있다.

  • 캐릭터의 이동 : 보는 시점으로 상하좌우 이동 / 카메라는 회전 X
  • 캐릭터의 회전 : 이동하는 방향으로 마네킹이 회전
  • 카메라 지지대 길이 : 450cm
  • 카메라 회전 : 마우스 이동에 따라 카메라 지지대가 회전
  • 카메라 줌 : 장애물 있으면 캐릭터 보이도록 장애물 앞으로 줌인
//카메라 설정

void AABCharacter::SetControlMode(int32 ControlMode)
{
	if (ControlMode == 0)
	{
		SpringArm->TargetArmLength = 450.0f;
		SpringArm->SetRelativeRotation(FRotator::ZeroRotator);
		SpringArm->bUsePawnControlRotation = true;
		SpringArm->bInheritPitch = true;
		SpringArm->bInheritRoll = true;
		SpringArm->bInheritYaw = true;
		SpringArm->bDoCollisionTest = true;
		bUseControllerRotationYaw = false;
    }
}

→ 카메라의 방향과 상관없이 시선 방향, 좌우 방향으로만 이동한다.

→우리는 카메라 방향을 중심으로 이동 방향을 변경해야 한다.

→이동 방향은 FVector이고, FVector를 얻기 위해 FRotator(컨트롤 회전) 데이터가 필요하다.   

컨트롤 회전 값으로부터 회전 행렬을 생성한 후, 원하는 방향 축을 대입해 캐릭터가 움직일 방향을 정한다.

※언리얼에서 "시선 방향은 X축" / "우측 방향은 Y축"을 의미한다.

void AABCharacter::UpDown(float NewAxisValue)
{
	AddMovementInput(FRotationMatrix(GetControlRotation()).GetUnitAxis(EAxis::X), NewAxisValue);
}
void AABCharacter::LeftRight(float NewAxisValue)
{
	AddMovementInput(FRotationMatrix(GetControlRotation()).GetUnitAxis(EAxis::Y), NewAxisValue);
}

 

이동은 잘 하지만, X축만 보고 이동함.

움직이는 방향으로 캐릭터를 자동으로 회전시켜 주는 캐릭터 무브먼트 컴포넌트의 'OrientRotationToMovement' 기능이 있음.

//ABCharacter.cpp

void AABCharacter::SetControlMode(int32 ControlMode)
{
	if (ControlMode == 0)
    {
    	...
        GetCharacterMovement()->bOrientRotationToMovement = true;
        GetCharacterMovement()->RotationRate = FRotator(0.0f, 720.0f, 0.0f);
    }
}

<4>. 삼인칭 컨트롤 구현(디아블로 방식)

디아블로 방식은 다음과 같은 성질을 가지고 있다.

  • 캐릭터의 이동 : 상하좌우 키를 조합해 이동할 방향을 결정
  • 캐릭터의 회전 : 입력한 방향으로 회전
  • 카메라 길이 : 800cm
  • 카메라 회전 : 회전 없이 항상 고정으로 45도
  • 카메라 줌 : 없음
//카메라 설정

void AABCharacter::SetControlMode(EControlMode NewControlMode)
{
	switch(CurrentControlMode)
    {
	case EControlMode::DIABLO:
	ArmLengthTo = 800.0f;
	ArmRotationTo = FRotator(-45.0f, 0.0f, 0.0f);
	SpringArm->bUsePawnControlRotation = false;
	SpringArm->bInheritPitch = false;
	SpringArm->bInheritRoll = false;
	SpringArm->bInheritYaw = false;
	SpringArm->bDoCollisionTest = false;
	bUseControllerRotationYaw = false;
	GetCharacterMovement()->bOrientRotationToMovement = false;
	GetCharacterMovement()->bUseControllerDesiredRotation = true;
	GetCharacterMovement()->RotationRate = FRotator(0.0f, 720.0f, 0.0f);
	break;
    }
    ...
}

※컨트롤 회전이 가리키는 방향으로 부드럽게 회전하기

bUseControllerRotationYaw = false;
GetCharacterMovement()->bOrientRotationToMovement = false;
GetCharacterMovement()->bUseControllerDesiredRotation = true;
GetCharacterMovement()->RotationRate = FRotator(0.0f, 720.0f, 0.0f);

 

※SpringArm의 길이와 회전 값 서서히 변경하기 : FMath 클래스의 'InterpTo' 사용

 

 <5>. 컨트롤 설정 변경

두 가지 조작 방식이 서로 전환되도록, ViewChange라는 액션 매핑 하나를 추가해 준다.

  입력 설정(Shift+v)을 완료하면, 해당 키가 눌러질 때마다 SetControlMode함수에 다른 인자값이 들어가도록

  액션 매핑 입력 설정과 연동된 함수 : BindAction

  버튼이 눌렸는지(EInputEvent::IE_Pressed), 떼어졌는지(EInputEvent::IE_Released)

 

※카메라 길이가 부드럽게 전환되도록

  FMath 클래스의 InterpTo 명령어 사용.

 

 

※4.27에서 달라진 부분은 SpringArm의 RelativeRotation이 private기 때문에 Get, Set 함수로 설정해줘야 함!!!

 

#p.203,204

SpringArm->RelativeRotation = FMath::RInterpTo(SpringArm->RelativeRotation, ArmRotationTo, DeltaTime, ArmRotationSpeed);

=>

SpringArm->SetRelativeRotation(FMath::RInterpTo(SpringArm->GetRelativeRotation(), ArmRotationTo, DeltaTime, ArmRotationSpeed));

 

 

 

[이득우의 언리얼 C++ 게임개발의 정석] #7. 애니메이션 시스템의 설계

애니메이션 블루프린트의 기반을 이루는 '애님 인스턴스'클래스를 C++로 제작하고애님 인스턴스 클래스의 데이터를 기반으로 캐릭터가 애니메이션을 체계적으로 재생할 수 있도록스테이트 머

lbto.tistory.com

 

반응형