본문 바로가기

게임프로그래밍/실습1

[언리얼 실습] 27. 인터페이스 사용하기


목차

  1. 인터페이스 상속받기
  2. 상속받은 인터페이스 함수 정의하기

1. 인터페이스 상속받기

 

에너미 클래스에서 히트 인터페이스를 상속받아 이를 구현해보려고 한다.

class PRACTICE_API AEnemy : public ACharacter

 

에너미 클래스는 보는 것과 같이 ACharcter 클래스를 상속받고 있다. 여기에 추가로 인터페이스를 상속받아 보자.

 

#include "Interface/HitInterface.h"

 

상속을 받기 위해서는 당연히 헤더파일을 가져와야 하고

 

class PRACTICE_API AEnemy : public ACharacter, public IHitInterface

 

상속은 단순히 쉼표를 쓰고 원래 상속을 받던 방식으로 상속을 받으면 된다.

 

히트인터페이스를 상속 받았고 그 안에는 GetHit라는 순수가상함수가 존재한다. 이제 이를 오버라이드 하여 에너미 클래스에 맞게 사용하면 될 것이다.


2. 상속받은 인터페이스 함수 정의하기
public:
	AEnemy();
	virtual void Tick(float DeltaTime) override;
	virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;

	virtual void GetHit() override; // 새로추가

 

현재 오버라이드를 통해 함수를 구현하려고 하는데 나중에 인터페이스를 언리얼 형식으로 바꿔서 쓰면 이 부분도 살짝 고쳐야한다. 현재는 인터페이스를 순수가상함수로 구현하였으니 정통적인 방식으로 사용해보자.

 

GetHit 함수를 퍼블릭 영역에 넣은 이유는 추후 히트를 유발할 때 다른 클래스에서 에너미 클래스의 히트를 유발해야 할 수도 있기에 퍼블릭 영역에 넣었다.

 

만약 다른 클래스에서 쓸 일이 없을 것 같다면 프로텍티드 영역으로 옮기면 될 것이다.

 

이제 함수를 정의(오버라이드)해보자. 타격을 받았을 떄 타격지점을 입력받아 디버그 스피어로 그려보려고 한다. 그러기 위해서 함수의 매개변수를 고쳐야할 것 같다.

 

public:
	virtual void GetHit(const FVector& ImpactPoint) = 0;

 

인터페이스에서 함수의 매개변수를 바꾸었다.

 

이제 이를 에너미 클래스에서도 형식에 맞게 바꾸면 된다.

 

선언부를 바꾸었으면 이제 cpp 파일에서 정의를 하자.

 

#include "DrawDebugHelpers.h"

void AEnemy::GetHit(const FVector& ImpactPoint)
{
	if (GetWorld())
	{
		DrawDebugSphere(GetWorld(), ImpactPoint, 25.f, 12, FColor::Red, true);
	}
}

 

이제 이 함수를 무언가와 부딪혓을 때 호출해보자. 무기 클래스에서 호출해보려고 한다.

 

void AWeapons::OnBoxOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
{
	const FVector Start = BoxTraceStart->GetComponentLocation();
	const FVector End = BoxTraceEnd->GetComponentLocation();

	TArray<AActor*> ActorsToIgnore;
	ActorsToIgnore.Add(this);

	FHitResult HitResult;
	UKismetSystemLibrary::BoxTraceSingle(this,
		Start,
		End,
		FVector(5.f, 5.f, 5.f),
		BoxTraceStart->GetComponentRotation(),
		ETraceTypeQuery::TraceTypeQuery1,
		false,
		ActorsToIgnore,
		EDrawDebugTrace::ForDuration,
		HitResult,
		true
	);
}

 

무기 클래스를 보면 무기와 무엇인가 오버랩 이벤트가 발생했을 때 작동하는 함수가 있다.

 

여기서 HitResult에 부딪힌 액터의 값이 있고 이것에 에너미인지 확인한 후 히트 함수를 호출하면 될것이다. 하지만 액터가 에너미인지는 어떻게 확인할까?

 

지금 사용하려는 방법은 HitResult에 있는 액터가 HitInterace로 캐스팅이 가능한지 보고 가능하면 Hit 함수를 호출하는 방식으로 사용하려고 한다.

 

if (HitResult.GetActor())
{
	IHitInterface* HitInterace = Cast<IHitInterface>(HitResult.GetActor());
	if (HitInterace)
	{
		HitInterace->GetHit(HitResult.ImpactPoint);
	}
}

 

OnBoxOverlap 함수 끝부분에 해당 부분을 추가하자.

 

히트된 액터를 인터페이스로 캐스팅하고 캐스팅에 성공하면 GetHit를 호출한다. IHitInterface의 경우 에너미 클래스보다 상위 클래스이기 때문에 이런 식으로 캐스팅해도 정상적으로 주소를 저장할 수 있으며 GetHit의 경우 가상함수이기 때문에 에너미에서 정의된 함수가 호출될 것이다.

 

이제 컴파일 하고 디버그 스피어가 그려지는 지 확인해보자.

 

 

정상적으로 작동하는 것을 볼 수 있다.

 

이렇게 해서 인터페이스를 상속받았다. 이를 이용하면 에너미의 히트 반응을 구현할 수 있을 것이다.