본문 바로가기

언리얼게임프로젝트/슈팅게임 C++

충돌이벤트와 델리게이트 Delegate

키보드가 눌리면 InputAction과 Binding된 함수가 실행되게 했죠. 이런걸 Deligate라고 합니다.

이때는 binding될 함수만 만들어 사용하면 되었지만 나중에 처음부터 만들경우 Deligate 매크로를 사용해  Deligate화 하고 바인딩후 실행해야 합니다. (키보드 처리 로직이 선언, Deleifate화, 실행을 해서 안보일뿐이지만)

 

델리게이트 장점

  예를 들어 설명하자면, 애님인스턴스 클래스에서 캐릭터의 콤보 카운트를 전달받아 해당 몽타주 섹션을 재생하고, NextAttackCheck 노티파이가 발생할 때마다 캐릭터에 이를 전달할 델리게이트를 선언하였다고 가정하자. 노티파이 함수에서 이 델리게이트를 호출해주면 애님 인스턴스는 자신의 델리게이트를 사용하는 객체(캐릭터)가 어떤 것인지 몰라도 델리게이트에 연결된 함수만 호출하면 되므로, 다른 클래스와 연결되지 않는 의존성 없는 설계를 할 수 있다는 장점이 생긴다.

 

https://coding-hell.tistory.com/47

 

[UE4] 델리게이트(Delegate)

특정 객체가 해야 할 로직을 다른 객체가 대신 처리할 수 있도록 만드는 보편적인 설계의 개념이다. 언리얼 엔진의 델리게이트는 A객체가 B객체에게 작업 명령을 내릴 때 B객체에 자신을 등록하

coding-hell.tistory.com

 

 

[함수 포인터] 02. 콜백 함수와 델리게이트

콜백 함수(Callback function)와 델리게이트(Delegate)는 프로그램의 유연성과 확장성을 증가시켜주는 고급 프로그래밍 기법입니다.

jay9011.github.io

 

 

 

UE4 C++ Delegate 정리 & 샘플 프로젝트

개인적으로 UE4 C++에서 Delegate를 사용할 때 처음에 굉장히 에러를 많이 겪었습니다, 그래서 이번 포스팅은 UE4 C++에서 Delegate를 사용하는 방법에 대해 정리하고 샘플프로젝트도 만들었습니다. https

darkcatgame.tistory.com

 

 

[C#] 콜백 함수(Callback)는 무엇이고 대리자(Delegate)는 뭘까?

*이 글은 책을 바탕으로 공부한 글입니다. 개요 콜백(Callback)이란 개념을 처음 들은 것은 유니티를 공부할 때였다. 게임이란 분야 특성상, 비동기 처리가 주를 이루는 시점에 콜백이란 개념은 필

daekyoulibrary.tistory.com

 

이런 경우 Deligate의 매개변수와 연결되는 함수의 매개변수는 형태와 갯수가 같아야 합니다.

Bullet.cpp BeginPlay() 함수안에 다음을 입력하고 F12 정의로 이동해봅니다. 함수 원형을 보기 위해서입니다.

이번엔 FComponentBeginOverlapSignature 타입위를 우클릭 선언으로 이동하면

DELEGATE_SixParams() 가 나오는데

앞에서 4번째 UPrimitiveComponent부터 12개를 복사합니다.

UPrimitiveComponent*, OverlappedComponent, AActor*, OtherActor, UPrimitiveComponent*, OtherComp, 
int32, OtherBodyIndex, bool, bFromSweep, const FHitResult &, SweepResult

Bullet.h 헤더 아래 public:으로 오버랩되면 실행할 함수를 만듭니다. 중간중간 쉼표를 빼야 합니다.

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

Bullet.cpp로 이동 함수를 구현하고

void ABullet::OnBulletOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, 
	UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, 
	bool bFromSweep, const FHitResult& SweepResult)
{
}

Binding 해줍니다.

void ABullet::BeginPlay()
{
	Super::BeginPlay();
	boxComp->OnComponentBeginOverlap.AddDynamic(this, &ABullet::OnBulletOverlap);
	
}

AEnemyActor를 사용하기 위해 

#include "EnemyActor.h"

OnBulletOverlap 매개변수인 OtherActor는 충돌체이므로 EnemyActor로  Cast후 맞다면 디스트로이 해줍니다. 자기 자신 Bullet도 조건없이 지워줍니다.

void ABullet::OnBulletOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, 
	UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, 
	bool bFromSweep, const FHitResult& SweepResult)
{
	AEnemyActor* enemy = Cast<AEnemyActor>(OtherActor);
	if (enemy)
	{
		OtherActor->Destroy();
	}
    Destroy();
}

Enemy도 Player와 충돌처리를 하기위해 Delegation이 호출되면 실행될 함수를 만들고 연결해 줍니다. 이전과 동일합니다.

EnemyPawn.cpp BeginPlay()에

boxComp->OnComponentBeginOverlap.AddDynamic(this, &AEnemyActor::OnEnemyOverlap);

헤더에 Delligation 선언해주고

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

EnemyPawn.cpp  에서 구현해주고

void AEnemyActor::OnEnemyOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, 
	UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
{
	APlayerPawn* player = Cast<APlayerPawn>(OtherActor);
	if (player)
	{
		player->Destroy();
	}
	Destroy();
}

BeginPlay()에서 this 와 bind 해주고 (위에서 이미 했습니다.)

실행해서 적과 Player가 충돌시 사라지는지 체크합니다.

 

총알이 적과 충돌시 폭발 이펙트를 만들어 봅니다. 이벤트를 감지하고 좋은곳은 Bullet.cpp입니다. 폭발이벤트를 등록하기위해 Bullet.h에 파티클 변수를 선언합니다.

	UPROPERTY(EditAnywhere)
	class UParticleSystem* explosionFX;

Bullet.cpp에  UGameplayStatics를 사용하기 위해 인클루드 해줍니다.

#include "Kismet/GameplayStatics.h"

void ABullet::OnBulletOverlap() 안에 적과 겹칠경우 이펙트를 Spawn해 줍니다.