작성자 없음
작성자 정보가 삭제된 글입니다.
작성
·
56
0
제가 현재 NPC가 플레이어가 공격 범위 내에 없으면 쫓아오게 하였습니다. 이때 NPC에서 공격범위의 값을 바꾸고 싶어서 UPROPERTY로 변수를 선언을 하였습니다.
커스텀 데코레이터에서 공격범위 값을 가져오기 위해 Interface를 만들어서 캐스팅을 해주었습니다.
하지만 플레이를 해보면 Interface가 없다고 나옵니다. 뭐가 잘못된 것일까요..?
class LIFEOFLUCK_API IOLNPCInterface
{
GENERATED_BODY()
// Add interface functions to this class. This is the class that will be inherited to implement this interface.
public:
virtual float AttackRange() = 0;
};
#include "CoreMinimal.h"
#include "Character/OLCharacterBase.h"
#include "Interface/OLNPCInterface.h"
#include "OLNPCBasic.generated.h"
UCLASS()
class LIFEOFLUCK_API AOLNPCBasic : public AOLCharacterBase, public IOLNPCInterface
{
...
protected:
virtual float AttackRange() override;
UPROPERTY(EditAnywhere, Category = "AttackRange")
float AttackRangeValue = 160; // 공격 범위 값
};
float AOLNPCBasic::AttackRange()
{
return AttackRangeValue;
}
#include "AI/BTDecorator_AttackRange.h"
#include "AIController.h"
#include "BehaviorTree/BlackboardComponent.h"
#include "Interface/OLNPCInterface.h"
DEFINE_LOG_CATEGORY(Not);
UBTDecorator_AttackRange::UBTDecorator_AttackRange()
{
}
bool UBTDecorator_AttackRange::CalculateRawConditionValue(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) const
{
Super::CalculateRawConditionValue(OwnerComp, NodeMemory);
APawn* NPC = OwnerComp.GetAIOwner()->GetPawn();
if (NPC == nullptr)
{
UE_LOG(Not, Error, TEXT("No NPC"));
return false;
}
FName PlayerName = TEXT("Target");
APawn* Player = Cast<APawn>(OwnerComp.GetBlackboardComponent()->GetValueAsObject(PlayerName)); // 타겟인 플레이어 가져오기(캐스팅하기)
if (Player == nullptr)
{
UE_LOG(Not, Error, TEXT("No Target"));
return false;
}
IOLNPCInterface* NPCInterface = Cast<IOLNPCInterface>(NPC); // NPC가 인터페이스를 생성한 경우 캐스팅이 됨
if (NPCInterface)
{
UE_LOG(Not, Error, TEXT("No NPCInterface"));
return false;
}
float Distance = FVector::Dist(NPC->GetActorLocation(), Player->GetActorLocation()); // NPC와 플레이어 사이의 거리 구하기
float AttackRange = NPCInterface->AttackRange();
bool AttackRangeResult = Distance <= AttackRange;
UE_LOG(LogTemp, Display, TEXT("Distance: %f"), Distance);
UE_LOG(LogTemp, Display, TEXT("AttackRange: %s"), AttackRangeResult ? TEXT("True") : TEXT("False"));
return AttackRangeResult;
}
답변 3
1
그리고 제가 아래와 같이 NPC에서 정의를 하여 리턴값으로 넣어주었는데 이렇게 해도 되는 건가요..?
UPROPERTY(EditAnywhere, Category = "AttackRange")
float AttackRangeValue = 160; // 공격 범위 값
네 언리얼 엔진에서 인터페이스의 경우 강의에서 제시한대로 엔진 에디터의 [툴 > 새로운 C++ 클래스] 메뉴를 통해 별도의 파일로 생성하는 것을 권장합니다. 내부 관리를 위해 두 개의 클래스가 생성됩니다.
헤더파일 초기화도 차후 관리적인 측면에서 가급적 생성자에서 진행함으로 통일하시는 것이 좋을 것 같아요.
0
해결을 했습니다! 제가 착각하고 interface == nullptr을 했어야 하는데 nullptr을 빼먹고 안 적어서
인터페이스가 존재할 때 false가 되어서 이상하게 작동을 한 거였습니다.
0
안녕하세요, 인프런 AI 인턴입니다. ajkdfj님.
NPC가 인터페이스를 통해 공격 범위 값을 가져오는 과정에서 문제가 발생한 것으로 보입니다. 주어진 코드와 설명에서 몇 가지 점을 확인해보겠습니다.
인터페이스 구현 확인:
AOLNPCBasic
클래스가 IOLNPCInterface
를 구현하는 것으로 보이지만, 인터페이스의 함수 AttackRange()
를 정상적으로 오버라이드하고 있는지 확인이 필요합니다.UObject
를 상속받은 클래스에서만 인터페이스를 제대로 사용할 수 있습니다. Cast<IOLNPCInterface>(NPC)
의 형태로 캐스팅되는지 확인해야 합니다. 일반적으로 인터페이스의 메서드를 직접 호출할 수 없을 수도 있습니다. 인터페이스를 배우는 것이 아닌 UINTERFACE
키워드로 인터페이스를 선언해야 합니다.캐스팅 문제:
Cast<IOLNPCInterface>(NPC);
부분에서 제대로 캐스팅이 이뤄지지 않는 경우, NPC가 정말 AOLNPCBasic
타입으로 생성된 것인지 확인이 필요합니다.Cast
가 null을 반환하게 됩니다.로그 확인:
UE_LOG(Not, Error, TEXT("No NPCInterface"));
로그가 거짓으로 나올 경우, 이는 Cast
가 실패했음을 의미합니다. 이 경우 Cast
의 결과를 null 체크하여 문제를 추적해야 합니다.인터페이스 규칙 확인:
UInterface
로 선언하기 때문에 IOLNPCInterface
가 일반 클래스를 상속받는 것인지, 언리얼 엔진의 인터페이스 구조를 제대로 활용하고 있는지 확인해볼 필요가 있습니다.인터페이스 초기화 누락:
AOLNPCBasic
의 인스턴스가 생성될 때 IOLNPCInterface
와 연결되지 않았다면, 메서드 호출이 불가능할 수도 있습니다.아래는 관련된 다른 질문 답변 링크입니다:
- Unreal 인터페이스 사용 시 발생하는 일반적인 문제
- 인터페이스의 올바른 구현 방법과 적용 사례
위의 점검 사항들을 확인한 후에도 해결되지 않는다면 실질적으로 인터페이스 구현과 사용이 맞는지를 다시 한번 점검해 보실 것을 권장드립니다.
저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다.
현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏
추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.
답해주셔서 감사합니다!
언리얼 엔진 문서에서 읽어보니 인터페이스에서 함수를 선언할 때 순수가상함수로 선언을 하지 않았는데 언리얼 엔진 문서와 동일하게 작성을 해야 하는 건가요?
아님 강의에서 배운 것도 언리얼 엔진에서 제안하는 방식인 건가요?