본문 바로가기

언리얼C++게임개발/07.애니메이션 시스템의 설계

[애니메이션시스템] 폰과 데이터 연동

게임을 플레이하면서 실제 폰의 속도에 따라 다른 애니메이션을 재생하기 위해서는 프레임마다 폰의 속력과 애님 인스턴스의 CurrentPawnSpeed 값이 동일해야 한다. 이를 위해 폰의 Tick함수에서 애님인스턴스의 CurrentPawnSpeed에 쓰거나 애님인스턴스의 Tick에서 폰의 속도 정보를 가져온 후 이를 CurrentPawnSpeed에 업데이트하는 방법이 있다 후자로 구현해본다 

애님인스턴스 클래스는 틱마다 호출되는 NativeAnimationUpdate함수를 가상 함수로 제공한다. 그래서 ABAnimInstance에 이를 상속받은 하나의 함수를 선언한다.

 

폰과 애님 인스턴스 데이터 연동

  • 폰의 Tick 함수에서 애님 인스턴스의 CurrentPawnSpeed 조정
  • 애님 인스턴스의 Tick에서 폰의 속도 정보를 가져와 CurrentPawnSpeed 업데이트
    • 애님 인스턴스 클래스에서 틱마다 호출되는 NativeUpdateAnimation 가상 함수 제공

 

ABAnimInstance.h

public:
	UABAnimInstance();
	virtual void NativeUpdateAnimation(float DeltaSeconds) override;​

 

  • TryGetPawnOwner : 애님인스턴스시스템의 틱에서 폰에 접근해 폰의 속력값을 얻기위해 제공되는 함수이다.

ABAnimInstance.cpp

void UABAnimInstance::NativeUpdateAnimation(float DeltaSeconds)
{
	Super::NativeUpdateAnimation(DeltaSeconds);

	// 유효한 Pawn 오브젝트의 포인터 받아옴
	auto Pawn = TryGetPawnOwner();
	if (::IsValid(Pawn))
	{
		CurrentPawnSpeed = Pawn->GetVelocity().Size();
	}
}
 
  • 게임 엔진은 틱마다 입력시스템>게임로직>애니메이션 시스템순으로 로직을 실행한다. 이는 플레이어의 의지인 입력값을 받은 후 그것을 해석해 폰을 움직이게 만들고, 폰의 최종 움직임과 맞는 애니메이션을 재생시키는 것이 자연스럽기 때문이다. 
  • 만일 게임로직단계에서 폰이 제거되었다면 그뒤 애니메이션 로직에서는 유효하지않은 폰을 참조해 에러가난다. 이를 방지하기 위해 TryGetPawnOwner함수로 유효한 Pawn객체 포인터를 받아와 속도를 구해  CurrentPawnSpeed에 저장한다.
  • 애님 인스턴스의 틱에서 폰에 접근해 애니메이션을 생성하는 방법이 일반적이지만.반대로 폰에서 스켈레탈 메시컴포넌트의 GetAnimation함수를 사용해서 접근할 수  있다. 

ABAnimInstance.h

void SetPawnSpeed(float NewPawnSpeed) {CurrentPawnSpeed = NewPawnSpeed;}

ABAnimInstance.cpp

void UABAnimInstance::NativeUpdateAnimation(float DeltaSeconds) {
Super::NativeUpdateAnimation(DeltaSeconds);

Character.cpp

ABAnimInstance.h
//...
//...
//...
auto ABAnimInstance = Cast<UABAnimInstance>(GetMesh()->GetAnimInstance());
if(nullptr != ABAnimInstance){
ABAnimInstance->SetPawnSpeed(GetVelocity().Size());

두가지 방법은 비슷하지만 전자의 방식이 애니메이션 로직과 폰의 로직을 분리할 수 있다.애니메이션이 필요없는 서버코더에서도 동작하기 때문이다.

 

'언리얼C++게임개발 > 07.애니메이션 시스템의 설계' 카테고리의 다른 글

점프의 구현  (0) 2023.11.26
스테이트 머신 제작  (1) 2023.11.26
애니메이션 블루프린트  (0) 2023.11.04