UE4 C++ Interface + Anim Notify 사용법
게임 구현하면서 서로 다른 클래스끼리 통신을 할때 각 클래스에 Interface클래스를 상속시켜서 쉽게 통신을 할 수 있습니다.
해당 게시글에서는 Interface + Notify를 이용하여 장전하는 애니메이션에서 장전되는 순간 함수가 호출되는 기능을 만들어 보겠습니다.
1. TPS 샘플 프로젝트에 장전하는 애니메이션 기능 추가
ACharacther.h
#include "EngineMinimal.h"
#include "GameFramework/Character.h"
#include "TestCharacter.generated.h"
UCLASS(config=Game)
class ATestCharacter : public ACharacter
{
GENERATED_BODY()
...
...
...
private :
//! 애니메이션 시퀸스 변수
UPROPERTY(EditDefaultsOnly, Category = Animation, Meta = (AllowPrivateAccess = true))
class UAnimSequenceBase* m_pAnimSequence_Reload;
ACharacter.cpp
ACharacter::ACharacter()
{
...
...
...
static ConstructorHelpers::FObjectFinder<UAnimSequenceBase> Asset_AnimMtg(TEXT("AnimSequence'/Game/Reload_Rifle_Ironsights.Reload_Rifle_Ironsights'")); //! 경로 입력
if (Asset_AnimMtg.Succeeded())
{
m_pAnimSequence_Reload = Asset_AnimMtg.Object; //! 시퀸스 변수 세팅
}
...
...
...
}
//! 키바인딩 함수 -> 애니메이션을 Default Slot에 재생
void ACharacter::Action_Reload()
{
UAnimMontage* pAnimationMtg = GetMesh()->GetAnimInstance()->PlaySlotAnimationAsDynamicMontage(m_pAnimSequence_Reload, TEXT("DefaultSlot"), 0.3f, 0.3f, 1.0f);
PlayAnimMontage(pAnimationMtg, 1.0f);
}
애니메이션 블루프린트의 Anim Grap에 Default Slot 노드 추가합니다, Slot을 이용해서 Full Body 애니메이션을 돌릴 예정입니다.
장전 애니메이션 재생기능 세팅 완료
2. Interface Class 제작
Itf_AnimationNotify.h
#include "CoreMinimal.h"
#include "UObject/Interface.h"
#include "Itf_AnimationNotify.generated.h"
// This class does not need to be modified.
UINTERFACE(MinimalAPI)
class UItf_AnimationNotify : public UInterface
{
GENERATED_BODY()
};
/**
*
*/
class TEST_API IItf_AnimationNotify
{
GENERATED_BODY()
public:
//! 사용할 Interface 함수 코드 추가 (여러 개 가능)
UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "Itf_Reload") //! Blueprint상에서 사용할 수 있도록 UFunction세팅
void Itf_ReloadDone(int nTestValue);
};
Itf_AnimationNotify.cpp 파일은 따로 수정하지 않습니다,
ACharacter.h
#include "Itf_AnimationNotify.h" //! Interface클래스 Include
#include "EngineMinimal.h"
#include "GameFramework/Character.h"
#include "TestCharacter.generated.h"
UCLASS(config=Game)
class ATestCharacter : public ACharacter, public IItf_AnimationNotify //! Interface 클래스 상속
{
GENERATED_BODY()
...
...
...
public :
//! 실제 구현 부 함수 정의
UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "Itf_Reload")
void Itf_ReloadDone(int nTestValue);
virtual void Itf_ReloadDone_Implementation(int nTestValue) override;
...
...
...
}
ACharacter.cpp
...
...
//! Interface함수 호출시 호출될 함수 선언
void ACharacter::Itf_ReloadDone_Implementation(int nTestValue)
{
UE_LOG(LogTemp, Warning, TEXT("Reload Done_%d"), nTestValue);
}
...
...
정의부분에서는 "Implementation"가 붙은 함수와 붙지 않은 함수 2개를 만들었지만 cpp선언에서는 "Implementation"가 붙은 함수만 작성합니다.
이것으로 Interface함수 세팅은 완료입니다.
인터페이스 함수 호출하는 법
ACharacter* pCharacter = FindActor("Charactor"); //! 해당 클래스 포인터 가져오기
if (ACharacter->GetClass()->ImplementsInterface(UItf_AnimationNotify::StaticClass()) == true) //! 해당 클래스에 해당 Interface클래스가 존재하는지 확인
{
IItf_AnimationNotify::Execute_Itf_ReloadDone(pCharacter, 123456); //! 함수 호출,
//! 1번 인자 : 호출할 클래스
//! 2번 인자 뒤 : 정의한 함수 인자
}
다른 클래스에서 호출할때는 정의한 함수 명 앞에 "Execute_"를 붙여야 합니다.
2. Anim Notify 제작 후 Interface 연동
Anim Notify Blueprint 클래스를 제작합니다.
Override함수를 생성하여 위 사진과 같이 Interface함수를 호출하는 노드를 제작합니다.
장전 애니메이션에서 장전이 완료되는 부분에 Notify 추가하고 우측 디테일 패널에서 인자값을 넣을 수 있습니다.
로그로 테스트 결과 성공적으로 Notify + Interface가 동작되는 것을 확인 했습니다.
참고자료
https://wiki.unrealengine.com/Interfaces_in_C%2B%2B