CAnimInstance.h
#pragma once
#include "CoreMinimal.h"
#include "Animation/AnimInstance.h"
#include "CAnimInstance.generated.h"
UCLASS()
class U2110_03_API UCAnimInstance : public UAnimInstance
{
GENERATED_BODY()
protected:
UPROPERTY(BlueprintReadOnly, EditAnywhere, Category = "Animation")
float Speed;
UPROPERTY(BlueprintReadOnly, EditAnywhere, Category = "Animation")
float Direction;
UPROPERTY(BlueprintReadOnly, EditAnywhere, Category = "Animation")
bool bEquipped; //총이 장착 되었는가 판단
public:
virtual void NativeBeginPlay() override;
virtual void NativeUpdateAnimation(float DeltaSeconds) override;
private:
class ACharacter* OwnerCharacter;
};
CAnimInstance.cpp
#include "CAnimInstance.h"
#include "Global.h"
#include "GameFramework/Character.h"
#include "05_TPS/IRifle.h" //플레이어 통해서 Rifle에서 가져오기
void UCAnimInstance::NativeBeginPlay()
{
Super::NativeBeginPlay();
OwnerCharacter = Cast<ACharacter>(TryGetPawnOwner());
}
void UCAnimInstance::NativeUpdateAnimation(float DeltaSeconds)
{
Super::NativeUpdateAnimation(DeltaSeconds);
if (OwnerCharacter == nullptr) return;
Speed = OwnerCharacter->GetVelocity().Size2D();
Direction = CalculateDirection(OwnerCharacter->GetVelocity(), OwnerCharacter->GetControlRotation());
IIRifle* rifle = Cast<IIRifle>(OwnerCharacter);
if (!!rifle)
bEquipped = rifle->GetEquipped();
}
Rifle이 누가 가질지 모른다 플레이어가 될지 다른 캐릭터가 될지. 이걸 인터페이스를 만들어서 해당 인터페이스를 가지면 총을 갖고 있다고 간주 하는 것
인터페이스
인터페이스 클래스는 (잠재적으로) 무관한 클래스 세트가 공통의 함수 세트를 구현할 수 있도록 하는 데 쓰입니다. 그대로라면 유사성이 없었을 크고 복잡한 클래스들에 어떤 게임 함수 기능을 공유시키고자 하는 경우 매우 좋습니다. 예를 들어 트리거 볼륨에 들어서면 함정이 발동되거나, 적에게 경보가 울리거나, 플레이어에게 점수를 주는 시스템을 가진 게임이 있다 칩시다. 함정, 적, 점수에서 ReactToTrigger (트리거에 반응) 함수를 구현하면 될 것입니다. 하지만 함정은 AActor
에서 파생될 수도, 적은 특수 APawn
또는 ACharacter
서브클래스일 수도, 점수는 UDataAsset
일 수도 있습니다. 이 모든 클래스에 공유 함수 기능이 필요하지만, UObject
말고는 공통 조상이 없습니다. 이럴 때 인터페이스를 추천합니다.
인터페이스 클래스 선언은 일반 언리얼 클래스 선언과 비슷하나, 크게 두 가지 차이점이 있습니다. 첫째, 인터페이스 클래스는 UCLASS 매크로 대신 UINTERFACE 매크로를 사용하며, UObject
를 직접 상속하는 대신 UInterface
를 상속합니다.
둘째, UINTERFACE 클래스는 실제 인터페이스가 아닙니다. 언리얼 엔진의 리플렉션 시스템에 보이도록 하기 위해서만 존재하는 비어 있는 클래스입니다. 다른 클래스에서 상속하게 되는 실제 인터페이스는 같은 클래스 이름에 첫 글자만 "U" 에서 "I" 로 바뀝니다.
인터페이스는 정의 될 때 I 로 정의된다.
.h 파일에서
#pragma once
#include "ReactToTriggerInterface.generated.h"
UINTERFACE(Blueprintable)
class UReactToTriggerInterface : public UInterface
{
GENERATED_BODY()
};
class IReactToTriggerInterface
{
GENERATED_BODY()
public:
/** 이 오브젝트를 활성화시키는 트리거 볼륨에 반응합니다. 반응에 성공하면 true 를 반환합니다. */
UFUNCTION(BlueprintCallable, BlueprintImplementableEvent, Category="Trigger Reaction")
bool ReactToTrigger() const;
};
함수를 .h 파일에 직접 작성할 수 있는데, 기본적으로 아무 것도 하지 않는 함수이거나 false, 0, 비어 있는 스트링 반환처럼 사소한 동작을 하는 함수의 경우 종종 그렇게 합니다. 보다 복잡한 함수는 .cpp 파일에 작성하여 컴파일 시간을 줄일 수 있습니다. 순수 가상 (pure virtual) 함수가 지원됩니다. 여기 샘플 함수는 .h 파일에 작성해도 될만큼 간단하긴 하지만, .cpp 파일에 작성하도록 하겠습니다. (ReactToTriggerInterface.cpp
와 같은) cpp 파일에 이제 다음과 같은 부분이 있을 것입니다:
bool bIsImplemented = OriginalObject->GetClass()->ImplementsInterface(UReactToTriggerInterface::StaticClass()); // OriginalObject 가 UReactToTriggerInterface 를 구현한다면 bIsImplemented 는 true 가 됩니다.
IReactToTriggerInterface* ReactingObject = Cast<IReactToTriggerInterface>(OriginalObject); // OriginalObject 가 UReactToTriggerInterface 를 구현한다면 ReactingObject 는 null 이외의 값이 됩니다.
블루프린트가 이 인터페이스를 구현할 수 있도록 하려면, Blueprintable
메타데이터 지정자를 사용해야 합니다. 블루프린트 클래스가 덮어쓰려는 모든 인터페이스 함수는 BlueprintNativeEvent
또는 BlueprintImplementableEvent
여야 합니다. BlueprintCallable
마킹된 함수는 여전히 호출은 가능할 것이나, 덮어쓰기는 불가능합니다. 다른 모든 함수는 블루프린트에서 접근할 수 없을 것입니다.
인터페이스는 순수가상함수를 포함한다고 되어있다. 재정의를 전재로 한다는 말 만약 C클래스 이면 override 사용하면 된다. 그런데 받은것이 자식이 C가 아니라 블루프린트 라면 그러면 재정의 할려면, BlueprintNativeEvent
또는 BlueprintImplementableEvent
여야 한다