본문 바로가기

게임프로그래밍/실습1

[언리얼 실습] 7. Overlab Event 생성


목차

  1. 서론
  2. 아이템 클래스 만들기
  3. C++ 클래스를 기반으로 블루프린트 클래스 만들기

1. 서론

 

이제 캐릭터의 이동에 관한 부분은 끝났으니 공격과 관련된 부분을 해야할 차례이다. 하지만 그전에 무기(아이템) 클래스를 만들어 캐릭터에 장착하는 부분을 해보려고 한다.

 

캐릭터가 아이템 근처에 가면 무기를 집을 수 있게 할 것인데 그러기 위해서 우선 캐릭터가 아이템에 오면 반응을 할 수 있게 오버랩 이벤트를 만들어 보려고 한다.


2. 아이템 클래스 만들기

 

아이템 클래스를 만들어 여기에 오버랩 이벤트를 주자.

 

아이템을 조종하거나 할 일은 없기 때문에 그냥 액터 클래스를 기반으로 만들면 된다.

 

이제 C++에서 이 액터에 오버랩 이벤트를 주자. 오버랩 이벤트를 주기 위해서 오버랩 할 영역을 만들어야 하는데 SphereComponent를 이용할 것이다.

 

class USphereComponent;

UCLASS()
class PRACTICE_API AMyActor : public AActor
{
	GENERATED_BODY()
	
public:	

	AMyActor();
	virtual void Tick(float DeltaTime) override;

protected:
	virtual void BeginPlay() override;

private:
	UPROPERTY(VisibleAnywhere)
	UStaticMeshComponent* ItemMesh;

	UPROPERTY(VisibleAnywhere)
	USphereComponent* SphereComponent;

};

 

private 영역을 만들고 그곳에 스피어컴포넌트를 담을 변수를 선언하였다. 스피어 컴포넌트의 경우 헤더파일이 필요하기 때문에 전방전언을 하고 cpp파일에서 헤더파일을 인클루드 하려고 한다.

 

또한 아이템 클래스에 매시도 설정해줄 예정이라 매시를 저장할 변수도 추가하였다.

 

이제 CPP 파일에서 스피어 컴포넌트와 스태틱매시 컴포넌트를 생성해보자

 

AMyActor::AMyActor()
{
	PrimaryActorTick.bCanEverTick = true;

	ItemMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("ItemMeshComponent"));
	RootComponent = ItemMesh;

	SphereComponent = CreateDefaultSubobject<USphereComponent>(TEXT("SphereComponent"));
	SphereComponent->SetupAttachment(GetRootComponent());

}

 

생성자부분에서 매시컴포넌트와 스피어컴포넌트를 만들고 매시컴포넌트를 루트컴포넌트로 그리고 스피어 컴포넌트를 매시컴포넌트에 어태치를 했다.

 

스피어 컴포넌트는 원시컴포넌트에서 유래하는데 이 원시 컴포넌트에는 델리게이트를 가지고 있어 이를 이용해 오버랩 이벤트를 생성할 수 있다.

 

 

비주얼 스튜디오에서 PrimitiveComponent.h 파일을 열고 BeginOverlap을 찾으면 델리게이틀 만들때 필요한 매크로 선언을 볼 수 있고 이곳 들어갈 매개변수들을 볼 수 있다.

 

매크로 구문중 DELEGATE_"여기" 에 있는 부분인 매개변수의 갯수를 말한다.

 

이제 델리게이트를 통해 오버랩 이벤트를 만들어보자.

 

void OnSphereOverlap();

protected:
	virtual void BeginPlay() override;

	void OnSphereOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult);

이 함수에 델리게이트로 연결할껀데 델리게이트가 전달해줄 매개변수를 받아야한다. 그렇기 때문에 매개변수를 설정해야하는데 위의 PrimitveComponent.h 파일에서 볼 수 있었던 Params를 그대로 가져오면 된다.

 

그러면 이렇게 함수를 만들 수 있다.

 

매개변수들의 의미하는 것은 각각 다음과 같다.

 

UPrimitiveComponent* OverlappedComponent : 충돌을 발생시킨 컴포넌트. 쉽게 말해 여기서는 스피어 컴포넌트를 말한다.

AActor* OtherActor : 이 클래스의 충돌 컴포넌트(바로 위 컴포넌트)에 충돌한 액터

 UPrimitiveComponent* OtherComp: 이 클래스의 충돌 컴포넌트에 충돌한 컴포넌트

 

이하 ChatGPT의 설명

 

  • int32 OtherBodyIndex:
    충돌한 콜리전의 인덱스입니다. 이는 물리 엔진에서 여러 개의 콜리전 본체(Body)를 가질 수 있는 경우 해당 본체의 인덱스를 나타냅니다.
  • bool bFromSweep:
    충돌이 스윕(Sweep) 테스트에서 발생했는지를 나타냅니다. 스윕 테스트는 오브젝트가 특정 위치에서 출발해 움직이면서 충돌 여부를 확인하는 방식입니다. true이면 스윕 테스트에서 발생한 충돌임을 의미합니다.
  • const FHitResult& SweepResult:
    스윕 테스트 결과를 담고 있는 구조체입니다. 충돌한 위치, 충돌의 세부 정보(예: 충돌한 표면의 노멀 벡터 등)를 포함하고 있습니다. bFromSweep이 true일 때만 유효한 값입니다.

이제 이 함수를 델리게이트와 바인딩 해보자. 델리게이트와 바인딩하기 위해서는 언리얼 엔진의 리플렉션 시스템에 노출되어야 한다고 한다.

 

UFUNCTION() 매크로를 함수 선언 위에 입력하자

UFUNCTION()
void OnSphereOverlap(
	UPrimitiveComponent* OverlappedComponent, 
	AActor* OtherActor,
    UPrimitiveComponent* OtherComp,
    int32 OtherBodyIndex,
    bool bFromSweep,
    const FHitResult& SweepResult
    );

 

 

이제 이 함수를 델리게이트와 바인드 해보자.

 

void AItem::BeginPlay()
{
	Super::BeginPlay();

	SphereComponent->OnComponentBeginOverlap.AddDynamic(this, &AItem::OnSphereOverlap);
	
}

 

델리게이트에 전달해야할 인자로는 첫번째는 콜백함수가 있는 오브젝트의 포인터를 말한다. 아이템 클래스를 쓸 거기 때문에 this를 입력하자. 두번째는 콜백함수의 주소이다.

 

우리가 위에 만든 함수를 입력하면 된다.

 

이제 함수를 정의해보자

 

void AItem::OnSphereOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
{
	const FString OtherActorName = OtherActor->GetName();
	if (GEngine)
	{
		GEngine->AddOnScreenDebugMessage(1, 3.f, FColor::Cyan, OtherActorName);
	}
}

 

간단하게 블루프린트의 PrintString 기능을 만들어 다른 액터의 이름을 출력할 수 있게 하였다.

 


3. C++ 클래스를 기반으로 블루프린트 클래스 만들기

 

이제 이 클래스를 기반으로 블루프린트 클래스를 만들어 월드에 배치를 해보자.

 

 

C++ 클래스를 우클릭하여 블루프린트 클래스를 만든다.

 

 

다음과 같이 블루프린트 편집창이 뜨면 스피어의 크기를 300까지 늘려보자. 매시는 적당히 아무거나 써서 화면에 보일 수 있게 하였다.

 

 

액터의 이름이 아주 잘 뜨는 것을 볼 수 있다.

 

이제 다음에는 오버랩이 끝날때(스피어 컴포넌트에서 나갈때) 이벤트가 발생하게 해보겠다.