Enemy(5)

groot616·2024년 5월 6일
0

언리얼5공부복습용

목록 보기
22/22

이제 팔라딘은 캐릭터를 공격할 수 있다.
팔라딘이 공격하면 캐릭터도 동일하게 경직이 생기면서 움찔거리는 애니메이션을 재생해야 한다.
팔라딘이 가진 애니메이션을 그대로 이용하기 위해 IK Retargeting 을 이용한다.
먼저 캐릭터의 T포즈와 동일하게 팔라딘의 T포즈를 다운로드한 후
root 본을 추가하기 위해 블렌더를 사용한다.
기존에 사용하던 SKM_Paladin 을 방금 root 본을 추가한 스켈레톤으로 변경하기 위해 파일명을 SKM_Paladin 으로 변경한 후 드래그드랍한다.
Rigs 폴더를 생성하고 팔라딘의 IK Rig 를 생성한다.
우측 Details 패널의 previewSKM_Paladin 으로 설정하고 지난번과 동일하게 HipsRetarget Root 로 잡고 체인을 생성해준다.
RTG_Paladin 이라는 IK Retargeter 를 생성해주고
우측의 Details 패널에서 SourceTarget 을 각각 IK_PaladinIK_Wraith 로 지정해준다.
상단의 Edit Pose 를 클릭해 Wraith 의 자세를 Paladin 과 동일하게 T포즈로 변경시킨다.
우측 하단의 Asset Browser 탭에서 여러 애니메이션을 이용해서 정상적으로 Retargeting 되는지 미리 확인한다.
Retargeting 하기 전에 Root 체인을 선택하고, 상단의 Translation ModeGlobally Scaled 로 변경한다.

  • None
    retarget 대상의 특정 본들의 이동이 source 포즈로부터 변경되지 않고 유지된다.
    retarget 대상의 스켈레톤의 이동을 변경하지 않고, 다른 요소들만 조정하는 것을 의미한다.
  • Globally Scaled
    retarget 대상의 특정 본의 위치 이동이 원본 애니메이션(source의 애니메이션)의 본의 오프셋에 retarget 스켈레톤의 전역 스케일을 곱한 값으로 설정된다는 것을 의미한다.
    전역 스케일은 retarget root bone 사이의 상대 높이 차이에 의해 결정된다.
  • Absolute
    retarget 대상의 특정 본의 위치 이동이 원본 애니메이션(source의 애니메이션)의 본의 절대적인 위치로 설정된다는 것을 의미한다.
    retarget 대상의 애니메이션에서의 스켈레톤 조정을 정확하게 할 수 있다.
    대충 retarget 할 때 skeletone bone 사이에 차이(실제로 움직이면 오프셋의 변화가 생김)가 있고, 해당 차이값을 skeleton bone 의 오프셋(위치)에 곱해서 조정한다는 의미인것 같다.
    경로를 지정해주고 Export 를 누른다.
    retarget 한 애니메이션을 열고, Asset Details 탭에서 EnableRootMotion 을 체크해제했을 때, 캐릭터가 뒤로 움직이면 성공적으로 애니메이션 추출이 완료된 것이다.

이제 캐릭터의 React Montage 를 생성해야 한다.
기존의 몽타주 파일도 가독성을 높히기 위해 AM_WraithAttackAM_WraithArming 으로 변경해주고, Wraith_Skeleton 기반 AM_WraithHitReact 몽타주를 생성한다.
파일을 열고 생성한 애니메이션들을 추가해준 뒤 Section Name 을 정해주고, Clear 버튼을 눌러 애니메이션이 연속재생되지 않도록 한다.
피격시 생성되는 사운드도 Play Sound 노이파이를 이용해서 추가해준다.
BP_Wraith 파일을 열고, HitReactMontage 에 생성한 AM_WraithHitReact 를 설정해준다.
이제 코드를 수정해야 한다.

  • BaseCharacter.h
...
protected:
	virtual void BeginPlay() override;
    // 피격시 실행 함수
    virtual void GetHit_Implementation(const FVector& ImpactPoint) override;
    ...

Enemy.cpp 에서 사용하는 GetHit_Implementation() 함수에서 HealthBar 관련 함수 제외한 나머지 부분은 캐릭터도 사용해야 하므로, 해당부분을 잘라내서 BaseCharacter 클래스로 옮긴 후 리팩토링을 진행한다.

  • BaseCharacter.cpp
...
void ABaseCharacter::GetHit_Implementation(const FVector& ImpactPoint)
{
	if(IsAlive())
    {
    	DirectionalHitReact(ImpactPoint);
    }
    else
    {
    	Die();
    }
    
    PlayHitSound(ImpactPoint);
    spawnHitParticles(ImpactPoint);
}
  • Enemy.cpp
...
void AEnemy::GetHit_Implementation(const FVector& ImpactPoint)
{
	Super::GetHit_Implementation(ImpactPoint);
    
	ShowHealthBarWidget();
}
...

그리고 WraithCharacter 클래스의 GetHit_Implementation() 함수에서는 BaseCharacter 클래스의 GetHit_Implementation() 함수를 가져오기만 하면 되므로 해당 부분도 수정한다.

  • WraithCharacter.cpp
...
void AWraithCharacter::GetHit_Implementation(const FVector& ImpactPoint)
{
	Super::GetHit_Implementation(ImpactPoint);
   	//	PlayHitSound(ImpactPoint);	삭제
    //	spawnHitParticles(ImpactPoint);	삭제
}

실행하고 피격당하면 피격 애니메이션이 재생되는 것을 확인할 수 있다.
추가로 오류때문에 Enemy 클래스에 있던 DirectionalHitReact() 함수에 피격 몽타주 재생 함수가 포함되어 있다.
캐릭터 클래스에서 GetHit_Implementation() 을 사용하기 위해선 BaseCharacter 클래스의 protected 섹션으로 DirectionalHitReact() 함수를 옮기고 virtual 선언을 해주어야 한다.
그리고 다시 Enemy 클래스로 돌아와서 DirectionalHitReact() 선언부에 override를 추가해주면 정상적으로 작동한다.

오류가 몇개 있는데 공격도중 피격당하면 공격이 끝날 때 발생하는 노티파이에 도달하지 못하고, 이는 캐릭터의 상태가 여전히 ECS_Attacking 상태임을 의미한다. 즉 다시 공격을 시도하면 이미 공격중인 상태이므로 공격을 하지 못하는 문제가 발생한다.
또한 피격도중엔 공격하지 못하도록 구현해야 하는데 피격 도중에도 공격이 가능한 상태인 문제가 있다.

0개의 댓글