GAS_07_무장 상태 애니메이션 전환 시스템 설계

2025. 5. 6. 17:10·내배캠/GAS(Gameplay Ability System)

📌 애니메이션 전환 시스템

한 캐릭터가 여러 종류의 무기(권총, 소총, 저격총 등)를 사용한다고 하면, 각 무기 타입마다 애니메이션이 다를 것이다.
이것을 각 무기마다 Anim Graph에 직접 노드를 추가한다면 유지보수가 매우 어려워지게 된다.

언리얼의 Lyra 프로젝트의 경우도 무기가 여러 종류가 있는데, "Anim Layer Interface"를 사용해서 각 무기별 애니메이션 로직을 레이어별로 분리하여 처리하였다.
이 설계 방향은 무기나 상태 확장에 유연하고 애니메이션 그래프의 복잡도가 크게 감소하게 된다.

 

✅ Anim Layer Interface 생성 및 적용

에디터에서 Animation Layer Interface를 생성하고 클래스 이름을 "ALI_Hero"로 명명하였다.
기본 Animation Layer 이름을 "ArmedLocomotionState"로 변경해주었고, 이게 설정 끝이다.

 

 

기본적으로 설정되어있는 ABP_Hero에서 Property Access 노드를 추가한다.
OwningHeroCharacter→HeroCombatComponent→CurrentEquippedWeaponTag를 설정한다.

 

Locomotion을 다음과 같이 정리한다.
현재 이 AnimInstance를 소유하고 있는 캐릭터의 CombatComponent에 접근하여, 현재 장착중인 무기 Tag를 확인한다.
유효하다면 ArmedLocomotionState를 사용하고 현재 장착 중인 무기가 없다면, 비무장 Locomotion으로 설정한다.

 

마지막으로 앞서 만들었던 Animation Layer Interface인 ALI_Hero를 설정해준다
이 인터페이스로 무기별로 AnimInstance가 달라도 하나의 인터페이스로 공통 동작을 호출할 수 있게 된다.

 

✅ Anim Layer Interface를 상속 받은 ABP_Layer 구현

이전에 AnimInstacne 구조 설계할 때 생성했던 "WarriorHeroLinkedAnimLayer" 클래스로 각 무기 전용 Anim Layer(ABP)를 만들 것이다.

 

🔹 WarriorHeroLinkedAnimLayer.h

#pragma once

#include "CoreMinimal.h"
#include "AnimIstances/RPGBaseAnimInstance.h"
#include "WarriorHeroLinkedAnimLayer.generated.h"

class UWarriorHeroAnimInstance;

UCLASS()
class RPG_API UWarriorHeroLinkedAnimLayer : public URPGBaseAnimInstance
{
	GENERATED_BODY()
	
public:
	UFUNCTION(BlueprintPure, meta = (BlueprintThreadSafe))
	UWarriorHeroAnimInstance* GetHeroAnimInstance() const;
};

🔹 WarriorHeroLinkedAnimLayer.h

#include "AnimIstances/Hero/WarriorHeroLinkedAnimLayer.h"
#include "AnimIstances/Hero/WarriorHeroAnimInstance.h"

UWarriorHeroAnimInstance* UWarriorHeroLinkedAnimLayer::GetHeroAnimInstance() const
{
    return Cast<UWarriorHeroAnimInstance>(GetOwningComponent()->GetAnimInstance());
}
메인으로 사용되는 AnimInstance에서 GroundSpeed를 가져와야 하므로, Instance 반환 함수를 구현하였다.

 

 

에디터로 돌아와, "WarriorHeroLinkedAnimLayer"를 상속받는 ABP를 생성해준다.

 

이 ABP도 마찬가지로 앞서 생성했던 Animation Layer Interface를 구현한다.
좌측 "ArmedLocomotionState"를 더블클릭 해서 Animation Layer 세부 구현을 진행한다.

 

"Blendspace Player" 노드를 생성한 뒤 클릭해서 Detail 창에서 몇가지 설정을 해준다.
Y값은 사용하지 않기 때문에 "Expose As Pin"을 눌러 핀을 없애주었고, Blend Space에 "Expose As Pin"을 눌러 핀을 활성화 해주었다.

 

PropertyAcess 노드를 만든 뒤, 앞서 구현했던 "GetHeroAnimInstance" 함수를 통해 AnimInstance에서 GroundSpeed값을 가져온다.

 

"Blendspace Player" 노드의 X축 핀에 GroundSpeed 값을 연결해주고, Blend Space는 변수로 승격시켜준다.

 

지금 만든 "MasterAnimLayer_Hero" 클래스를 상속받는 ABP 클래스를 생성한다.
이 클래스를 상속받는 ABP가 각 무기마다 전용 Animation을 담는 클래스가 될 것이다.

 

이 Axe 무기 전용 Layer에 BlendSpace만 설정해준다. 앞선 포스팅에서 BlendSpace 1D 만드는 과정을 서술했으므로 BS를 만드는 과정은 따로 정리하지 않는다.

 

✅ 각 무기 클래스에 AnimLayer 정보 저장

각 무기마다 AnimLayer(ABP 클래스)를 저장해놓고, 특정 무기를 들었을 때 해당 ABP를 캐릭터에 동적으로 연결해줌으로써, 자동으로 무기별 전용 애니메이션이 동작하게 만드는 구조이다.

먼저 프로젝트 전체 구조체를 정리할 클래스를 만들고 그 안에 AnimLayer를 저장할 구조체를 선언한 뒤, 무기에 해당 구조체를 멤버변수로 가지고 있게할 것이다.
이후 GA_EquipAxe와 같은 Ability에서 무기를 장착하면 SkeletalMesh에 AnimLayer를 연결해주도록 한다.

🔹 RPGStructTypes.h

#pragma once

#include "RPGStructTypes.generated.h"

class UWarriorHeroLinkedAnimLayer;

USTRUCT(BlueprintType)
struct FRPGHeroWeaponData
{
	GENERATED_BODY()

	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
	TSubclassOf<UWarriorHeroLinkedAnimLayer> WeaponAnimLayerToLink;
};
방금 만들었던 도끼 전용 AnimLayer와 같이 무기별 AnimLayer를 담을 수 있는 구조체를 선언하였다.

 

🔹 WarriorHeroWeapon.h

#pragma once

#include "CoreMinimal.h"
#include "Items/Weapons/RPGWeaponBase.h"
#include "RPGTypes/RPGStructTypes.h"
#include "WarriorHeroWeapon.generated.h"

UCLASS()
class RPG_API AWarriorHeroWeapon : public ARPGWeaponBase
{
	GENERATED_BODY()
	
public:
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "WeaponData")
	FRPGHeroWeaponData HeroWeaponData;
};
플레이어 무기 클래스에 앞서 만든 구조체 타입 변수를 선언해준다.

 

🔹 HeroCombatComponent.h

#pragma once

#include "CoreMinimal.h"
#include "Components/Combat/PawnCombatComponent.h"
#include "HeroCombatComponent.generated.h"

class AWarriorHeroWeapon;

UCLASS()
class RPG_API UHeroCombatComponent : public UPawnCombatComponent
{
	GENERATED_BODY()
	
public:
	UFUNCTION(BlueprintCallable, Category = "RPG|Combat")
	AWarriorHeroWeapon* GetHeroCarriedWeaponByTag(FGameplayTag InWeaponTag) const;
};

🔹 HeroCombatComponent.cpp

#include "Components/Combat/HeroCombatComponent.h"
#include "Items/Weapons/WarriorHeroWeapon.h"

AWarriorHeroWeapon* UHeroCombatComponent::GetHeroCarriedWeaponByTag(FGameplayTag InWeaponTag) const
{
   return Cast<AWarriorHeroWeapon>(GetCharacterCarriedWeaponByTag(InWeaponTag));
}
GA에서 HeroCombatComponet를 가져와서 Tag기반으로 바로 무기 클래스를 가져와, 무기 클래스 안의 AnimLayer 데이터를 가져올텐데 조금 더 BP에서 코드를 단순화 하기 위해, HeroWeapon타입으로 캐스팅해 반환하는 헬퍼 함수를 작성해주었다.

 

컴파일 후, 에디터로 돌아와 "GA_Hero_EquipAxe"에 해당 무기안에 AnimLayer 데이터를 가져와서 연결시켜주었다.
그리고 Hero Combat Component에 현재 장착중인 무기의 Tag를 설정해주었다.

 

마지막으로 해당 무기에 AnimLayer 데이터를 할당해준다.

 

 

🔔 테스트 결과

무기가 계속 추가되더라도 기존 메인으로 사용되는 "ABP_Hero"에서 수정하는 것이 아닌,
"MasterAnimLayer_Hero" 클래스를 상속 받은 "AnimLayer_HeroAxe"와 같은 무기 전용 ABP를 만들어서 무기에 넣어주기만 하면 자동으로 해당 애니메이션이 재생되는 구조가 되었다.
이로써 슈팅 게임에서 권총 혹은 소총, 저격총 등 여러 무기를 장착했을 때 개별적인 애니메이션을 보다 더 쉽게 적용시킬 수 있을 것 같다.

 

 

 

'내배캠 > GAS(Gameplay Ability System)' 카테고리의 다른 글

GAS_09_무기 공격 애니메이션 구현  (0) 2025.05.07
GAS_08_무장 상태에 따른 Ability + IMC 설계  (0) 2025.05.07
GAS_06_Ability Input Action 바인딩 및 GA(무기장착) 활성화  (0) 2025.05.06
GAS_05_플레이어 전용 GameplayAbility  (0) 2025.05.05
GAS_04_Combat Component  (0) 2025.05.05
'내배캠/GAS(Gameplay Ability System)' 카테고리의 다른 글
  • GAS_09_무기 공격 애니메이션 구현
  • GAS_08_무장 상태에 따른 Ability + IMC 설계
  • GAS_06_Ability Input Action 바인딩 및 GA(무기장착) 활성화
  • GAS_05_플레이어 전용 GameplayAbility
동그래님
동그래님
  • 동그래님
    개발자 동그래
    동그래님
  • 전체
    오늘
    어제
    • 분류 전체보기 (210)
      • 공부 (51)
        • Code Cata (50)
      • 내배캠 (151)
        • TIL (50)
        • C++ (37)
        • Unreal Engine (48)
        • GAS(Gameplay Ability System.. (16)
      • Project (7)
        • Gunfire Paragon (5)
        • Arena Fighters (1)
  • 블로그 메뉴

    • 링크

    • 공지사항

    • 인기 글

    • 태그

    • 최근 댓글

    • 최근 글

    • hELLO· Designed By정상우.v4.10.3
    동그래님
    GAS_07_무장 상태 애니메이션 전환 시스템 설계
    상단으로

    티스토리툴바