EDR_Project / EDR_Boss_Knight (2) 루트 모션

24.11.23 EDR_Boss_Knight의 수정 사항 입니다.

공격 애니메이션이 재생될 때 제자리 스텝이 있는 공격인데도 제자리 걸음을 하는 문제점이 있었습니다.

 

처음에는 애니메이션 몽타주에서 캐릭터가 발을 내려놓을때 노티파이를 찍어 그때마다 앞으로 조금씩 이동하게 할려고 했었으나 캐릭터가 순간이동을 하는 문제가 생겼습니다.

 

조금 찾아보니 루트 모션이라는 기능이 있는 것을 알아서 적용하였습니다.

 

다만 기존에 사용했던 애니메이션은 inplace로 루트 모션을 지원하지 않기때문에 루트모션을 지원하는 애니메이션으로 다시 리타겟팅 해주었습니다.

https://lgj415415.tistory.com/73

 

언리얼 엔진 5 / 애니메이션 루트 모션

애니메이션 루트 모션루트 모션이란 간단하게 애니메이션을 재생할때 루트 본을 함께 움직여 주어 애니메이션의 움직임이 실제 캐릭터의 움직임이 되도록 해주는 기능입니다.https://dev.epicgames.c

lgj415415.tistory.com

이를 이용해 공격 할 때 스텝이 있을경우 움직이도록 하였습니다.

 

EDR_Boss_Knight.h

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "MyCharacter.h"
#include "EDR_Enemy_Weapon.h"
#include "EDR_Boss_Knight.generated.h"

/**
 * 
 */
UCLASS()
class EDR_API AEDR_Boss_Knight : public AMyCharacter
{
	GENERATED_BODY()
	AEDR_Boss_Knight();
	
protected:
	// Called when the game starts or when spawned
	virtual void BeginPlay() override;
};
반응형

EDR_Boss_Knight.cpp

// Fill out your copyright notice in the Description page of Project Settings.


#include "EDR_Boss_Knight.h"
#include "EDR_Enemy_Weapon.h"
#include "GameFramework/CharacterMovementComponent.h"
AEDR_Boss_Knight::AEDR_Boss_Knight()
{
	// hp 재정의
	hp = 100.0f;
	AttackDamage = 40.0f;
	AttackRange = 400.0f;
	AttackRadius = 200.0f;

	SkillDamage = 40.0f;
	SkillRange = 400.0f;
	SkillRadius = 200.0f;


	//GetCharacterMovement()->MaxWalkSpeed = 200.0f;

	// 캐릭터 메시랑 캡슐콜리전
	RootComponent = GetCapsuleComponent();
	GetMesh()->SetupAttachment(GetCapsuleComponent());
	GetCapsuleComponent()->SetCapsuleHalfHeight(88.0f);

	GetCapsuleComponent()->SetCapsuleRadius(34.0f);
	GetMesh()->SetRelativeLocationAndRotation(FVector(0.0f, 0.0f, -88.0f), FRotator(0.0f, -90.0f, 0.0f));


	// 메시 받아오기
	static ConstructorHelpers::FObjectFinder<USkeletalMesh>MODEL(TEXT("/Game/BLACKSUN_BOSSBUNDLE1/Characters/Thral/SK_ThrallRigged.SK_ThrallRigged"));
	if (MODEL.Succeeded())
	{
		GetMesh()->SetSkeletalMesh(MODEL.Object);
	}	
	

	// 크기 1.6배 키우기
	SetActorScale3D(FVector(1.6f, 1.6f, 1.6f));	
	
	
	
	
	// 애니메이션 관련

	// 전투 시작 애니메이션

	static ConstructorHelpers::FObjectFinder<UAnimMontage> FIGHTSTART_MONTAGE(TEXT("/Script/Engine.AnimMontage'/Game/GJ/Animation/Enemy_Anim/KnighEnemy/NoneBattle/Boss_BattleEntrance_RM_Montage.Boss_BattleEntrance_RM_Montage'"));
	if (FIGHTSTART_MONTAGE.Succeeded())
	{
		FightStartMontage = FIGHTSTART_MONTAGE.Object;
	}


	// 공격
	static ConstructorHelpers::FObjectFinder<UAnimMontage> ATTACK_MONTAGE1(TEXT("/Game/GJ/Animation/Enemy_Anim/KnighEnemy/Attack/Boss_Attack_HandAndSwordSwing_RM_Montage.Boss_Attack_HandAndSwordSwing_RM_Montage"));
	if (ATTACK_MONTAGE1.Succeeded())
	{
		AttackMontage.Add(ATTACK_MONTAGE1.Object);
	}
	static ConstructorHelpers::FObjectFinder<UAnimMontage> ATTACK_MONTAGE2(TEXT("/Game/GJ/Animation/Enemy_Anim/KnighEnemy/Attack/Boss_Attack_Running_Simple_RM_Montage.Boss_Attack_Running_Simple_RM_Montage"));
	{
		AttackMontage.Add(ATTACK_MONTAGE2.Object);
	}
	static ConstructorHelpers::FObjectFinder<UAnimMontage> ATTACK_MONTAGE3(TEXT("/Game/GJ/Animation/Enemy_Anim/KnighEnemy/Attack/Boss_Attack_Swing_RM_Montage.Boss_Attack_Swing_RM_Montage"));
	{
		AttackMontage.Add(ATTACK_MONTAGE3.Object);
	}
	static ConstructorHelpers::FObjectFinder<UAnimMontage> ATTACK_MONTAGE4(TEXT("/Game/GJ/Animation/Enemy_Anim/KnighEnemy/Attack/Boss_Attack_SwingAndSlam_RM_Montage.Boss_Attack_SwingAndSlam_RM_Montage"));
	{
		AttackMontage.Add(ATTACK_MONTAGE4.Object);
	}
	static ConstructorHelpers::FObjectFinder<UAnimMontage> ATTACK_MONTAGE5(TEXT("/Game/GJ/Animation/Enemy_Anim/KnighEnemy/Attack/Boss_Attack_Uppercut_RM_Montage.Boss_Attack_Uppercut_RM_Montage"));
	{
		AttackMontage.Add(ATTACK_MONTAGE5.Object);
	}


	// 스킬 애니메이션 몽타주 저장
	static ConstructorHelpers::FObjectFinder<UAnimMontage> SKILL_MONTAGE(TEXT("/Game/GJ/Animation/Enemy_Anim/KnighEnemy/Attack/Boss_Attack_ChargedComboAttack_RM_Montage.Boss_Attack_ChargedComboAttack_RM_Montage"));
	if (SKILL_MONTAGE.Succeeded())
	{
		SkillMontage = SKILL_MONTAGE.Object;
	}

	// 사망 애니메이션 몽타주 저장
	static ConstructorHelpers::FObjectFinder<UAnimMontage>DEATHANIM(TEXT("/Game/GJ/Animation/Enemy_Anim/KnighEnemy/GiantGolemIdleDeath01_Montage.GiantGolemIdleDeath01_Montage"));
	if (DEATHANIM.Succeeded())
	{
		DeathMontage = DEATHANIM.Object;
	}

	// 사운드 관련

	// 공격 히트시 사운드 저장
	static ConstructorHelpers::FObjectFinder<USoundCue>HITSOUNDCUE1(TEXT("/Game/Sword_Fighting_SFX/Cues/Blunt_Weapon_Hits_Flesh_3_Cue.Blunt_Weapon_Hits_Flesh_3_Cue"));
	if (HITSOUNDCUE1.Succeeded())
	{
		HitSoundCue.Add(HITSOUNDCUE1.Object);
	}	// 공격 히트시 사운드 저장
	static ConstructorHelpers::FObjectFinder<USoundCue>HITSOUNDCUE2(TEXT("/Game/Sword_Fighting_SFX/Cues/Blunt_Weapon_Hits_Flesh_1_Cue.Blunt_Weapon_Hits_Flesh_1_Cue"));
	if (HITSOUNDCUE2.Succeeded())
	{
		HitSoundCue.Add(HITSOUNDCUE2.Object);
	}	// 공격 히트시 사운드 저장
	static ConstructorHelpers::FObjectFinder<USoundCue>HITSOUNDCUE3(TEXT("/Game/Sword_Fighting_SFX/Cues/Blunt_Weapon_Hits_Flesh_5_Cue.Blunt_Weapon_Hits_Flesh_5_Cue"));
	if (HITSOUNDCUE3.Succeeded())
	{
		HitSoundCue.Add(HITSOUNDCUE1.Object);
	}


	// 공격 미스시 사운드 저장
	static ConstructorHelpers::FObjectFinder<USoundCue>MISSSOUNDCUE1(TEXT("/Game/Sword_Fighting_SFX/Cues/Sword_Hit_1_Cue.Sword_Hit_1_Cue"));
	if (MISSSOUNDCUE1.Succeeded())
	{
		MissSoundCue.Add(MISSSOUNDCUE1.Object);
	}	// 공격 미스시 사운드 저장
	static ConstructorHelpers::FObjectFinder<USoundCue>MISSSOUNDCUE2(TEXT("/Game/Sword_Fighting_SFX/Cues/Sword_Hit_1_Cue.Sword_Hit_2_Cue"));
	if (MISSSOUNDCUE2.Succeeded())
	{
		MissSoundCue.Add(MISSSOUNDCUE2.Object);
	}	// 공격 미스시 사운드 저장
	static ConstructorHelpers::FObjectFinder<USoundCue>MISSSOUNDCUE3(TEXT("/Game/Sword_Fighting_SFX/Cues/Sword_Hit_1_Cue.Sword_Hit_5_Cue"));
	if (MISSSOUNDCUE3.Succeeded())
	{
		MissSoundCue.Add(MISSSOUNDCUE3.Object);
	}

}
void AEDR_Boss_Knight::BeginPlay()
{
	Super::BeginPlay();

	// 게임 실행시 캐릭터 손에 무기 장착
	FName WeaponSocket(TEXT("hand_rSocket"));
	CurrentWeapon = GetWorld()->SpawnActor<AEDR_Enemy_Weapon>(FVector::ZeroVector, FRotator::ZeroRotator);
	if (nullptr != CurrentWeapon)
	{
		CurrentWeapon->AttachToComponent(GetMesh(), FAttachmentTransformRules::SnapToTargetNotIncludingScale, WeaponSocket);
		//CurrentWeapon->SetActorRelativeRotation(FRotator(0.0f, 0.0f, 180.0f)); // 180도 회전
		CurrentWeapon->SetActorRelativeLocation(FVector(0.0f, 0.0f, -10.0f)); // 무기이동


		// 무기 크기 키우기
		CurrentWeapon->SetActorScale3D(FVector(2.0f));
	}
}

기존에 사용하던 애니메이션 몽타주를 루트모션을 지원하는 애니메이션 몽타주로 바꿔주었고, 애니메이션 몽타주 2개 추가하였습니다.

실행 화면