그냥 게임개발자

UE5 - Locomotion System[AnimationInstance(1)] 본문

UE5_Tutorial2

UE5 - Locomotion System[AnimationInstance(1)]

sudoju 2023. 10. 20. 22:56

Locomotion System 글은 아래 유튜버 분 영상을 통해 작성되는 점 참고드립니다.

 

https://www.youtube.com/watch?v=K1JMo1CvIro

 

 

오늘은 AnimInstance를 만들꺼다.

 

1. AnimInstance

2. AnimGraphe

 

바로 본론으로 들어가자.

 

일단 우리가 필요한 애니메이션 파일들을 받아주자.

위에 유튜브 영상에 들어가서 더보기 란을 클릭하면 Animation 다운받는 드라이브 주소가 나오니 다운받자.

애니메이션 임포트하는 방법은 위에서 보면 될 것 같다.


1. AnimInstance

애님 인스턴스 클래스를 만들어 블루프린트로 다시 만들자.

스켈레톤은 SK_Mannequin으로 해주자.

AnimGraph

필자는 이미 어느정도 만들었기에 애님그래프가 이렇게 되어있다.

 

애니메이션 변수들

애니메이션 변수들 또한 엄청 많다.

애님 그래프를 작성하기 전에 일단 클래스에서 작성할 것들을 작성해보자.

이번 포스팅은 걷기 뛰기만 작성할 예정이다.

 

1. 캐릭터가 앞, 뒤, 좌, 우 상태를 나타내는 Enum

2. 캐릭터의 속도와 지면속도

3. 움직이는 체크여부 변수

 

자 만들어보자.

 

1. 캐릭터가 앞, 뒤, 좌, 우 상태를 나타내는 Enum

2. 캐릭터의 속도와 지면속도

3. 움직이는 체크여부 변수

이것을 한꺼번에 만들어보자.


LocomotionAnimInstance.h

UENUM(BlueprintType)
enum class Movement_Input : uint8
{
	Forward		UMETA(DisplayName = "Forward"),
	Right		UMETA(DisplayName = "Right"),
	Backward	UMETA(DisplayName = "Backward"),
	Left		UMETA(DisplayName = "Left"),
};
/**
 * 
 */
UCLASS()
class PROJECT_S_API ULocomotionAnimInstance : public UAnimInstance
{
	GENERATED_BODY()
	
public:
// 생성자
	ULocomotionAnimInstance();
// 초기화
	virtual void NativeInitializeAnimation() override;
// 업데이트
	virtual void NativeUpdateAnimation(float DeltaTime) override;
// 캐릭터 진행 방향 
	void GetDirectionAngle();
    
public:
// 캐릭터 속도
	UPROPERTY(VisibleAnywhere, BlueprintReadwrite, Category = "Essential Movement Data", meta = (AllowPrivateAccess = "true"))
	FVector Velocity;
// 지면 속도    
	UPROPERTY(VisibleAnywhere, BlueprintReadwrite, Category = "Essential Movement Data", meta = (AllowPrivateAccess = "true"))
	float GroundSpeed;
// 떨어지는지 체크    
    	UPROPERTY(VisibleAnywhere, BlueprintReadwrite, Category = "Essential Movement Data", meta = (AllowPrivateAccess = "true"))
	bool IsFalling;
// 캐릭터 진행 방향
	UPROPERTY(VisibleAnywhere, BlueprintReadwrite, Category = "Direction", meta = (AllowPrivateAccess = "true"))
	Movement_Input E_MovementInput;
}

LocomtionAnimInstance.cpp

void ULocomotionAnimInstance::NativeInitializeAnimation()
{
	Super::NativeInitializeAnimation();
    // 초기화
	APawn* Pawn = TryGetPawnOwner();
	if (IsValid(Pawn))
	{
		Character = Cast<ASantosCharacter>(Pawn);
		MovementComponent = Character->GetCharacterMovement();
	}
}

void ULocomotionAnimInstance::NativeUpdateAnimation(float DeltaTime)
{
	Super::NativeUpdateAnimation(DeltaTime);
	if (Character != nullptr)
	{
		// 캐릭터의 현재 속도를 가져옴
		// 지면 속도는 xy축으로만 계산되므로 상하이동은 영향을 주지 않음
		Velocity = MovementComponent->Velocity;
		GroundSpeed = Velocity.Size2D();

		// 지면속도가 3.0f보다 크고 현재 가속도가 zero가 아닌지 확인이 되면 움직이는 것으로 확인
		ShouldMove = (GroundSpeed > 3.f && MovementComponent->GetCurrentAcceleration() != FVector::ZeroVector);

		IsFalling = MovementComponent->IsFalling();
		GetDirectionAngle();
	}
}

void ULocomotionAnimInstance::GetDirectionAngle()
{
	// 방향을 구한다.
	// CalculateDirection을 통해 2D 평면에서 두 점 사이의 각도나 방향을 계산한다.
	FVector NewVector = FVector(Velocity.X, Velocity.Y, 0.f);
	DirectionAngle = FRotator::NormalizeAxis(CalculateDirection(NewVector, Character->GetActorRotation()));

	/*UE_LOG(LogTemp, Warning, TEXT("현재 회전값 : %f"), Direction);*/
	if (DirectionAngle > -45.f && DirectionAngle <= 45.f)			// Direction의 회전값이 -45도와 45도 사이에 있으면 Forward방향
	{
		E_MovementInput = Movement_Input::Forward;
	}
	else if (DirectionAngle > 45.f && DirectionAngle <= 135.f)	// Direction의 회전값이 45도와 135도 사이에 있으면 Right방향
	{
		E_MovementInput = Movement_Input::Right;
	}
	else if (DirectionAngle > 135.f || DirectionAngle <= -135.f)	// Direction의 회전값이 135도와 -135도 사이에 있으면 Backward방향
	{
		E_MovementInput = Movement_Input::Backward;
	}
	else if (DirectionAngle > -135.f && DirectionAngle <= -45.f)	// Direction의 회전값이 -45도와 45도 사이에 있으면 Left방향
	{
		E_MovementInput = Movement_Input::Left;
	}
}

이렇게 애님 클래스를 작성했다.

빌드를 하고 블루프린트에서 빌드가 잘 되었는지 확인해보자(변수가 생긴다면 성공)


2. AnimGraphe

이제 우리는 애님 그래프를 작성해보자.

 

 

AnimGraph

필자의 애님 그래프는 위와 같이 작성되어 있다.

 

Locomotion 상태를 보자.

 

Locomotion과 LocomotinoCache

Locomotion을 캐시로 저장한다.

 

Idle과 Walk / Run Cycle

 

기본 Locomotion상태일때는 Idle을 재생하고

Idle -> Walk / Run Cycle

ShouldMove가 true가되었을 시 Walk / Run Cycle 스테이트로 가게 된다.

 

 

Idle

Idle의 상태를 보자.

Idle State

Idle 상태에서는 Random Sequence Player를 통해 랜덤한 Idle을 재생한다.

Random Sequence Player

랜덤한 값들을 통해 Idle을 플레이한다.

 

이제 Walk / Run Cycle을 보자.

Walk / Run Cycle

상당히 무언가 복잡해보이지만 하나씩 살펴보면 의외로 간단하다.

우리가 애님 클래스에 MovementInput라는 enum을 만들어 주었다.

그리고 우리는 그 값을 지금 현재 계속 업데이트 중에 있다.

그렇다면 이 값이 캐릭터가 움직일때마다 바뀐다라는 것을 알고 있다.

 

그렇다면 우리는 그거에 맞는 포즈를 설정해주면 된다.

Blend Poses (Movement_Input)

Blend Poses (Movement_Input) 생성을하자.

 

핀 생성

우리가 만든 enum의 핀들을 생성하자.

 

Blend Poses DefaultPose는 Idle로

우리가 설정한 E Movement Input의 변수 값을 통해 이 포즈가 설정이 될것이다.

그냥 기본 값에서는 Idle을 설정해주는 것으로 하면 된다.

 

그 전에 우리는 뛰기도 만들어야 하니 다시 cpp클래스로 가서 작성하자.

 

LocomotionAnimInstance.h

UCLASS()
class PROJECT_S_API ULocomotionAnimInstance : public UAnimInstance
{
	GENERATED_BODY()


.
.
.
.
.

	void GetIsSprint();


// 달리는지 체크    
    	UPROPERTY(VisibleAnywhere, BlueprintReadwrite, Category = "Essential Movement Data", meta = (AllowPrivateAccess = "true"))
	bool IsSprint;
}

 

LocomotionAnimInstance.cpp

 

.
.
.


void ULocomotionAnimInstance::NativeUpdateAnimation(float DeltaTime)
{
	Super::NativeUpdateAnimation(DeltaTime);
	if (Character != nullptr)
	{
    .
    .
    .
    
		GetIsSprint();
	}
}

void ULocomotionAnimInstance::GetIsSprint()
{
	if (IsValid(Character))
	{
		IsSprint = Character->IsSprint;
	}
}

 

이제 값을 얻어올 수 있다.

 

Forward 애니메이션

Is Sprint의 값에 따라 true면 Jog 애니메이션을 false면 Walk 애니메이션을 재생한다.

Fwd 애니메이션 적용 완료

이렇게 다 각자의 애니메이션을 적용 시켜주면 된다.

 

walk / run cycle 적용

이제 메인 스테이트 머신을 확인해보자.

 

Main States Machine

 

Main States

뭔가 많다..

하나하나 살펴보자.

 

Locomotion, Land, To Land
Locomotion

Locomotion - 캐시 된 Locomotion 애니메이션을 사용

Land에서 Locomotion 가는 조건

Land에서 Locomotion으로 가는 조건은 Automatic Rule과 ShouldMove가 true가 되었을 때 이동한다.

Automatic Rule은 애니메이션이 끝날 때즘에 이동한다는 조건이다.

Land

Land - 캐시 된 Locomotion 애니메이션 Addtive(첨가) 가중치를 더해 MM_Unarmed_Jump_RecoveryAddtive라는 애니메이션을 재생시킨다.

 

 

State Alias - To Land

To Land - State Alias라는 노드인데 이 노드는 Detail 패널에서 보면

To Land Detail Panel

위와 같이 체크가 되어있는 State들이 있다.

지금 현재 보면 Land와 FallLoop가 StateAlias

State Alias는 직접적인 트랜지션 룰 없이도 트랜지션이 작동한다.

즉 FallLoop 상태에서 IsFalling이 바로 false가 되는 순간 Land로 트랜지션이 된다.

ToLand에서 Land로 가는 조건
Jump

Jump의 상태를 살펴보자

FallLoop
Jump에서 FallLoop로 가는 조건

Jump에서 Fall Loop로 가는 조건은 Automatic Rule이다.

Jump

Jump애니메이션이다.

To Falling Alias

Locomotion에서 Jump로 Alias가 체크 되어 있다.

To Falling -> Jump

IsFalling이 true이고 Velocity.z(캐릭터 속도의 z값)이 100f 이상이면 Jump로 가게 된다.

To Falling -> Fall Loop

IsFalling이 true가 되었을 때 FallLoop으로 트랜지션이 된다.

 

후 이제 다음 포스팅은 4개의 애니메이션으로 8각 애니메이션을 구현하는 로직을 쓰려고 한다.

그다음 앉기, 구르기를 포스팅 할 예정이다.

여기까지 따라와주셔서 감사합니다.

'UE5_Tutorial2' 카테고리의 다른 글

언리얼의 타입과 크기  (1) 2023.12.29
명명 규칙  (1) 2023.12.29
UE_LOG  (1) 2023.12.29
Visual Studio 기본 세팅  (0) 2023.12.29