본문 바로가기

공부/이득우의 언리얼 프로그래밍

[Study] Part 2 - 캐릭터 애니메이션 설정 (4/15)

728x90
반응형

 

 

 

4강 캐릭터 애니메이션 설정

  • 정리
    • 캐릭터 애니메이션 생성과 설계
      1. C++클래스를 상속받은 애니메이션 블루프린트의 생성 방법의 이해
      2. 이벤트 그래프와 애님 그래프로 구성된 애니메이션 블루프린트의 구조 파악
      3. 애님 그래프를 사용한 애니메이션 시스템의 설계 방법의 학습

 

 

BP의 Animation
이미 생성되어 있는 Animation BluePrint

  • Skeletal Mesh Componet에 보면 애니메이션 모드가 Use Animation Blueprint로 설정되어 있다면, Anim Class로 등록되어 있는 클래스 정보를 캐릭터가 생성될 때 해당 클래스로부터 인스턴스를 생성해서 애니메이션을 담당하는 인스턴스 언리얼 오브젝트를 생성해서 관리를 시키도록 일임한다.
  • 이러한 애니메이션 블루프린트 시스템이 전체적인 캐릭터 모션을 담당한다고 이해하면 된다.
  • C++로 AnimInstace 클래스를 직접 만들고 애니메이션 블루프린트가 우리가 생성한 C++ 클래스를 상속받아서 기본적인 로직을 구현한 후에 AnimGraph를 사용하여 구체적인 모션을 지정하도록 설계

 

 

 

애니메이션을담당할 AnimInstance C++ 클래스를 생성해준다.
Animation>Animation Blueprint
Create Animation Blueprint

  • 이 후 애니메이션 블루프린트를 생성한다.
  • 애니메이션 블루프린트를 생성할 때 사용할 스켈레톤 메쉬를 선택하고 방금 만든 ABAnimInstance (AnimInstance C++클래스)를 Parent Class로 설정해준다.

 

 

 

 

	// 메쉬 지정
	// 적용하고 싶은 스켈레탈 메쉬의 Copy Reference 복붙
	static ConstructorHelpers::FObjectFinder<USkeletalMesh> CharacterMeshRef(TEXT("/Script/Engine.SkeletalMesh'/Game/InfinityBladeWarriors/Character/CompleteCharacters/SK_CharM_Cardboard.SK_CharM_Cardboard'"));
	if (CharacterMeshRef.Object)
	{
		GetMesh()->SetSkeletalMesh(CharacterMeshRef.Object);
	}

	// 애니메이션 지정
		// 적용하고 싶은 AnimInstance의 Copy Reference 복붙 + ''삭제 및 끝에 _C 붙이기
	static ConstructorHelpers::FClassFinder<UAnimInstance> AnimInstanceClassRef(TEXT("/Game/ArenaBattle/Animation/ABP_ABCharacter.ABP_ABCharacter_C"));
	if (AnimInstanceClassRef.Class)
	{
		GetMesh()->SetAnimInstanceClass(AnimInstanceClassRef.Class);
	}
  • ABCharacterBase.cpp

 

  • 설정해준 뒤, 그에 맞게 예전에 설정한 ABCharacterBase.cpp의 생성자 내용을 수정해준다.
  • 컴파일 후 에디터를 실행한다.

 

 

원하는 캐릭터로 변경된 걸 확인 할 수 있다.

 

 

 

 

  • 캐릭터 애니메이션 시스템의 생성
    • 스켈레탈 메시 컴포넌트의 애니메이션 블루프린트 클래스를 지정
    • 캐릭터가 초기화될 때 AnimInstance 클래스의 인스턴스를 생성
    • 캐릭터는 GetAnimInstance 함수를 사용해 애니메이션 인스턴스를 얻을 수 있음
    • 애니메이션 인스턴스는 GetOwningActor 함수를 사용해 자신을 소유한 액터 정보를 얻을 수 있음

캐릭터는 GetAnimInstance()를 통해 애니메이션 인스턴스를, 애니메이션 인스턴스는 GetOwningActor를 통해 캐릭터 액터 정보를 얻을 수 있다.

 

 

 

  • 캐릭터 애니메이션 시스템의 설계
    • 애니메이션 블루프린트는 이벤트 그래프와 애님 그래프의 두 영역으로 구성되어 있음
    • 이벤트 그래프
      • 이벤트로부터 상태를 파악할 수 있는 주요 변수 저장
    • 애님 그래프
      • 저장된 변수로부터 지정된 상태의 애니메이션을 재생
      • 애님 그래프의 복잡한 상태는 State Alias로 분리해 효과적으로 설계할 수 있음

 

이벤트 그래프 - 주요 변수 저장 / 애님 그래프 - 지정된 상태의 애니메이션을 재생

 

 

#pragma once

#include "CoreMinimal.h"
#include "Animation/AnimInstance.h"
#include "ABAnimInstance.generated.h"

UCLASS()
class ARENABATTLE_API UABAnimInstance : public UAnimInstance
{
	GENERATED_BODY()
	
public:
	UABAnimInstance();

protected:
	// AnimInstance가 처음 생성될 때 한 번 호출
	virtual void NativeInitializeAnimation() override;
	// 프레임마다 호출
	virtual void NativeUpdateAnimation(float DeltaSeconds) override;

	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Character)
	TObjectPtr<class ACharacter> Owner;

	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Character)
	TObjectPtr<class UCharacterMovementComponent> Movement; 

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Character)
	FVector Velocity;

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Character)
	float GroundSpeed;

	// 언리얼에서 bool 타입은 사이즈가 명확하지 않아서 integer형으로 선언하되, b라는 접두사를 붙여 다른 integer 형과 구분
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Character)
	uint8 bIsIdle : 1;

	// 움직이고 있는지, 쉬고 있는지
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Character)
	float MovingThreshould;

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Character)
	uint8 bIsFalling : 1;

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Character)
	uint8 bIsJumping : 1;

	// 움직이고 있는지, 쉬고 있는지
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Character)
	float JumpingThreshould;
};
  • UABAnimInstance .h
#include "Animation/ABAnimInstance.h"
#include "GameFramework/Character.h"
#include "GameFramework/CharacterMovementComponent.h"

UABAnimInstance::UABAnimInstance()
{
	MovingThreshould = 3.0f;
	JumpingThreshould = 100.0f;
}

// AnimInstance가 처음 생성될 때 한 번 호출
void UABAnimInstance::NativeInitializeAnimation()
{
	Super::NativeInitializeAnimation();

	// 오브젝트에 대한 포인트 값을 초기화
	Owner = Cast<ACharacter>(GetOwningActor());		// 형변환
	if (Owner)		// Null 값 확인
	{
		Movement = Owner->GetCharacterMovement();		// Movement를 통해 캐릭터 무브먼트 객체로 부터 값을 얻어올 수 있다.
	}
}

// 프레임마다 호출
void UABAnimInstance::NativeUpdateAnimation(float DeltaSeconds)
{
	Super::NativeUpdateAnimation(DeltaSeconds);

	// NativeInitializeAnimation()에서 가져온 값으로 로직 구성
	if (Movement)
	{
		Velocity = Movement->Velocity;
		GroundSpeed = Velocity.Size2D();
		bIsIdle = GroundSpeed < MovingThreshould;
		bIsFalling = Movement->IsFalling();
		bIsJumping = bIsFalling & (Velocity.Z > JumpingThreshould);
	}
}
  • UABAnimInstance .cpp

 

 

 

Animation Blueprint>My Blueprint

  • 애니메이션 블루프린트의 My Blueprint에서 기어박스 Show Inherited Variables 항목을 체크하면 상속받은 C++ 변수들을 확인할 수 있다.
  • 다음 변수들을 바탕으로 애님 그래프를 구성해서 사용하면 된다.

 

AnimGraph>StateMachine

  • State MachineAnimGraph전체적인 관리를 담당한다.

 

AnimGraph 로직 구현

  • 유니티의 애니메이터와 같이 상태에 따라 전이할 수 있도록 설정해줄 수 있다.
  • 이후 각 상태에 따라 애니메이션을 넣어주면 된다.

 

  • 속도에 따라 애니메이션이 블랜딩되도록 설정하기 위해서는 한가지 애니메이션 에셋이 필요하다.

 

 

 

Animation>Legacy>Blend Space 1D

  • Blend Space 1D를 사용하여 애니메이션을 블랜딩할 애니메이션 에셋을 만들어 준다.
  • 메쉬는 적용할 캐릭터의 스켈레톤 메쉬를 설정하면 된다.

 

 

 

Blend Space 1D>Axis Settings>Horizontal Axis

  • 가로값에 대한 셋팅을 설정해준다.
    • Idle > Walk > Run에 대한 애니메이션을 블랜딩해주기 위해서 사용할 값의 이름을 설정해주고, 해당 값의 범위 Min~Max를 설정해준다.

 

 

블랜딩에 사용할 애니메이션을 드래그 하여 값을 설정해준다.
Animation Blending

  • 값을 설정한 후 ctrl을 누른채로 하단에서 마우스를 움직이면 아까 설정한 GroundSpeed(0~500)에 따라 애니메이션이 블랜딩 되는 것을 실시간으로 확인할 수 있다.

 

 

Animation Blueprint

  • 이후 애니메이션 블루프린트로 돌아가면 Asset Browser에 만든 애니메이션 에셋(BS_IdleWalkRun)이 나타나게 되고, C++로 만든 Ground Speed 변수를 연결해주면 된다.

 

New Save cached pose
Connect cached pose

  • 애니메이션을 적용하기위해 cached pose를 만들어 준 뒤, 연결해준다.
  • 연결이 되었으면, Compile을 하고 확인한다.

 

 

 

Ground Speed에 따라 애니메이션이 블랜딩되는 모습

 

 

 

 

ToJump Priority Order

  • Jump를 하는 행동을 생각해봤을때, Falling무조건 Jump 애니메이션이 나타난 다음에 나타나야할 애니메이션이기 때문에 Priority Order를 Jump 애니메이션보다 후순위인 2로 설정해준다.

 

Jump>Falling
완성된 Anim Graph

  • Jump에서 Falling으로 넘어갈 때 Time Remaining(ratio) 노드를 사용하여 Jump 애니메이션이 끝나기 전에 Falling애니메이션이 시작될 수 있도록 설정해준다.
    • Time Remaining (ratio) (Warrior Jump) < 0.1

 

 

캐릭터 애니메이션이 정상적으로 동작하는 것을 확인할 수 있다.

 

 

 

 

 

 

해당 포스트는 인프런의 <이득우의 언리얼 프로그래밍 Part2 -언리얼 게임 프레임웍의 이해>
강의를 수강하고 정리한 내용입니다.
 

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

청강문화산업대학교에서 언리얼 엔진, 게임 수학, UEFN 게임제작을 가르치고 있습니다. - 이득우의 언리얼 C++ 프로그래밍, 넥슨 코리아 공식 교육 교재 선정 2023 - 스마일게이트 언리얼 프로그래

www.inflearn.com

 

728x90