본문 바로가기
Unreal Engine 5

언리얼 엔진5 - 충돌 이벤트 처리

by 니키티스 2026. 6. 6.

충돌했을 때 어떻게 스크립트에서 이를 감지하고 처리할까? 

스크립트 단에서 이를 처리하려면 보통 오버라이딩하는 방법과 동적 바인딩 둘 중 하나를 선택하여 처리가 가능하다.

어느 방법을 쓰든 거의 동일하게 구현이 가능한 것으로 보이며, 어느 것을 쓸지는 필요나 기호에 따라, 혹은 구조에 따라 결정하면 된다.

해당 부분은 다음 글을 참고했다(https://devshovelinglife.tistory.com/15).

 

[Unreal] 언리얼 충돌체 관련 함수와 이벤트(델리게이트) 바인딩 방법 #2

언리얼 엔진에선 두 가지의 충돌체가 존재한다. 하나는 메쉬(static 또는 skeletal)의 충돌체 그리고 충돌 컴포넌트(SphereComponent,BoxComponent 기타 등등). C++로 충돌체 이벤트 바인딩할 수 있는 방법 총

devshovelinglife.tistory.com

 

1. Overriding 방법

기존 메서드를 오버라이드하는 방식으로, 이미 형식이 정해져 있어 형식을 바꿀 수 없다.

AActor::NotifyHit

부딪혔을 때 발생하는 이벤트를 다룰 땐 NotifyHit 메서드를 오버라이딩하여 구현할 수 있다.

기본 API( https://dev.epicgames.com/documentation/unreal-engine/API/Runtime/Engine/AActor/NotifyHit )는 다음을 참고하였다.

virtual void NotifyHit  
(  
    class UPrimitiveComponent * MyComp,  
    AActor * Other,  
    class UPrimitiveComponent * OtherComp,  
    bool bSelfMoved,  
    FVector HitLocation,  
    FVector HitNormal,  
    FVector NormalImpulse,  
    const FHitResult & Hit  
)  
  • 다른 오브젝트에 부딪히거나, 다른 오브젝트가 해당 액터에 부딪혔을 때 호출
  • 물리 시뮬레이션 중에는 Simulation Generates Hit Events를 켜놔야 사용 가능하다.
 

NotifyActorBeginOverlap(AActor*) / NotifyActorEndOverlap(AActor*)

NofityHit과 유사하지만 충돌 혹은 겹치기 시작했을 때, 충돌 및 겹침이 끝날 때 호출된다.
형식은 다음과 같다.
virtual void AActor::NotifyActorBeginOverlap(AActor* OtherActor);

virtual void AActor::NotifyActorEndOverlap(AActor* OtherActor);

 

2. 동적 바인딩 방법

  • 위와 같이 override로 구현하는 방법도 있고, 충돌이 일어날 때 발생하는 이벤트 콜백을 추가할 수도 있다.
  • 다만 BeginPlay 이후에 바인딩되어야 해서, 오버라이드할 새 함수를 UFUNCTION으로 등록하고 AddDynamic으로 새 함수들을 바인딩한다.
 

OnComponentHit / OnComponentBeginOverlap / OnComponentEndOverlap

  • 부딪힐 때 호출 / 겹칠 때 호출 / 겹침이 끝날 때 호출
GetCapsuleComponent()->OnComponentHit.AddDynamic(this, &ACharacter::ActorIsHitting);
위와 같이 UPrimitiveComponent::OnComponentHit 에 동적 함수 바인딩을 진행하는 식으로 등록할 수 있다.
이때 OnComponentHit, OnComponentBeginOverlap, OnComponentEndOverlap은 각각 다음과 같은 시그니처를 가지고 있다.
 
/**
 * Delegate for notification of blocking collision against a specific component.  
 * NormalImpulse will be filled in for physics-simulating bodies, but will be zero for swept-component blocking collisions. 
 */
DECLARE_DYNAMIC_MULTICAST_SPARSE_DELEGATE_FiveParams( FComponentHitSignature, UPrimitiveComponent, OnComponentHit, UPrimitiveComponent*, HitComponent, AActor*, OtherActor, UPrimitiveComponent*, OtherComp, FVector, NormalImpulse, const FHitResult&, Hit );
/** Delegate for notification of start of overlap with a specific component */
DECLARE_DYNAMIC_MULTICAST_SPARSE_DELEGATE_SixParams( FComponentBeginOverlapSignature, UPrimitiveComponent, OnComponentBeginOverlap, UPrimitiveComponent*, OverlappedComponent, AActor*, OtherActor, UPrimitiveComponent*, OtherComp, int32, OtherBodyIndex, bool, bFromSweep, const FHitResult &, SweepResult);
/** Delegate for notification of end of overlap with a specific component */
DECLARE_DYNAMIC_MULTICAST_SPARSE_DELEGATE_FourParams( FComponentEndOverlapSignature, UPrimitiveComponent, OnComponentEndOverlap, UPrimitiveComponent*, OverlappedComponent, AActor*, OtherActor, UPrimitiveComponent*, OtherComp, int32, OtherBodyIndex);
여기서 잘 보면 특이하게도 델리게이트를 선언할 때
DECLARE_DYNAMIC_MULTICAST_SPARSE_DELEGATE_파라미터수
와 같은 식으로 선언하고 있는데, 
  • DYNAMIC_MULTICAST → 일대다 형태로 블루프린트 등록도 지원함
  • RetVal 없음 → 반환 값이 없다(MULTICAST는 원래 반환값이 없음)
  • SPARSE_DELEGATE → 메모리 절약을 위해 바운딩되지 않았을 땐 1바이트의 메모리만 소모하도록 한다. 그 대신, 훨씬 속도가 느리다.
기본적으로 해당 델리게이트에는 바인딩이 안되는 경우가 많아 SPARSE_DELEGATE로 처리한 것으로 보인다. 참고로 SPARSE_DELEGATE는 타고 들어가 보면 SparseDelegateClass라는 이름의 클래스로 정의되어 있는 것 같다.

SparseDelegateClass를 통해 SPARSE_DELEGATE 매크로가 선언되어 있다.

어쨌거나 형식을 확인해보면, OnComponentHit , OnComponentBeginOverlap , OnComponentEndOverlap 은 처음 세 개 파라미터를 제외한다면 다음과 같은 형식을 받아들이고 있다고 볼 수 있다.
// OnComponentHitDelegate에 등록 가능한 형식
void OnComponentHitDelegate(
    UPrimitiveComponent* HitComponent, 
    AActor* OtherActor, 
    UPrimitiveComponent* OtherComp, 
    FVector NormalImpulse,
    const FHitResult& Hit);

// OnComponentBeginOverlap에 등록 가능한 형식
void OnComponentBeginOverlapDelegate(
    UPrimitiveComponent* OverlappedComponent, 
    AActor* OtherActor, 
    UPrimitiveComponent* OtherComp, 
    int32 OtherBodyIndex, 
    bool bFromSweep, 
    const FHitResult& SweepResult);

// OnComponentEndOverlap에 등록 가능한 형식
void OnComponentEndOverlapDelegate(
    UPrimitiveComponent* OverlappedComponent, 
    AActor* OtherActor, 
    UPrimitiveComponent* OtherComp, 
    int32 OtherBodyIndex);

 

참고 글

https://devshovelinglife.tistory.com/15

댓글