콜리전과 콜리전 이벤트

 

작성 기준 버전 :: 4.21.1

 

콜리전(Collision)은 언리얼 엔진에서 물리적인 충돌이나 레이 캐스팅 실시간 처리를 해준다. 이러한 물리 시뮬레이션은 Collision Response(콜리전 반응) 및 Trace Response(트레이스 반응) 설정을 통해서 다른 오브젝트 유형과 어떻게 상호작용할지 정의된다.

 

블록(Block), 겹침(Overlap), 무시(Ignore)

 

충돌 작용은 블록(Block), 겹침(Overlap), 무시(Ignore)로 나누어진다.

 

 

블록은 충돌하는 두 오브젝트가 모두 블록이어야 두 오브젝트가 충돌했을 때, 겹치지 않고 서로에게 막히게 된다. 콜리전 옵션 중에 Simulation Generates Hit Event 프로퍼티를 true로 설정하면 이러한 충돌이 발생했을 때 Event Hit을 받아서 블루프린트나 디스트럭터블 액터, 트리거 등에 사용할 수 있고 이를 응용해서 총알에 맞아서 깨지는 유리창 등을 구현할 수 있다.

 

 

겹침은 다른 오브젝트를 통과시키지만, 만약 Generate Overlap Event가 활성화된 상태라면 Overlap Event를 발생시킨다. 이 겹침 이벤트가 발생하려면 두 오브젝트 모두 겹침 이상으로 설정되어 있어야 한다. 만약 한 쪽은 겹침이고 다른 한 쪽이 무시인 상태라면 겹침 이벤트는 발생하지 않는다.

 

 

무시는 모든 오브젝트와 트레이스를 통과시키며 어떠한 이벤트도 발생시키지 않는다.

 

 

콜리전 이벤트

 

콜리전이 발생시키는 이벤트를 다루는 방법에 대해서 배워보자.

 

히트 이벤트(Hit Event)

 

히트 이벤트는 블록 상태인 오브젝트들이 서로 충돌했을 때 발생하는 이벤트로 해당 오브젝트에게 통지된다. 히트 이벤트를 발생하게 하기 위해서는 우선 콜리전의 프로퍼티 중에 Simulation Generates Hit Event를 true로 설정해줘야 한다.

 

우선 히트 이벤트를 받아서 처리하기 위한 클래스를 BlockCollisionActor라는 이름으로 Actor 클래스를 상속받아서 생성하자.

 

 

그리고 비주얼 스튜디오로 가서 BlockCollisionActor.h에 다음 멤버 변수와 함수 선언 코드를 추가한다.

 

protected:
    virtual void NotifyHit(UPrimitiveComponent *MyComp, AActor *Other, UPrimitiveComponent *OtherComp, bool bSelfMoved, FVector HitLocation, FVector HitNormal, FVector NormalImpulse, const FHitResult &Hit) override;

public:   
    UPROPERTY(EditAnywhere)
    class UStaticMeshComponent* BoxMesh;

 

NotifyHit() 함수는 부모 클래스에서 상속받은 것으로 이것을 덮어씌워 작성함으로써 충돌이 발생했을 때 개발자가 원하는 동작을 처리하도록하는 것이 가능해진다. BoxMesh는 다른 물체와 충돌할 메시를 담을 변수이다.

 

그 다음엔 BlockCollisionActor.cpp로 가서 스태틱 메시 컴포넌트를 사용하기 위해서 다음 전처리기를 추가한다.

 

#include "Engine/Classes/Components/StaticMeshComponent.h"

 

ABlockCollisionActor::ABlockCollisionActor() 생성자 함수에 다음과 같이 BoxMesh 변수를 초기화하는 코드를 추가한다.

 

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

    BoxMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("BoxMesh"));
    RootComponent = BoxMesh;
}

 

그리고 아까 선언한 NotifyHit() 함수를 다음과 같이 충돌이 발생했을 때 로그를 출력하도록 구현한다.

 

void ABlockCollisionActor::NotifyHit(UPrimitiveComponent *MyComp, AActor *Other, UPrimitiveComponent *OtherComp, bool bSelfMoved, FVector HitLocation, FVector HitNormal, FVector NormalImpulse, const FHitResult &Hit)
{
    UE_LOG(LogTemp, Log, TEXT("NotifyHit"));
}

 

코드 작업이 마무리되었다면 프로젝트를 빌드하고 에디터로 돌아가서 히트 이벤트 테스트를 위한 작업을 진행해보자.

 

먼저 BlockCollisionActor를 레벨에 배치한다.

 

 

BlockCollisionActor의 디테일 패널에서 BoxMesh를 선택하고 비어있는 스태틱 메시 프로퍼티에 모드 패널의 큐브 스태틱 메시를 드래그래서 넣는다.

 

 

그 다음 디테일 패널에서 Collision 카테고리를 찾아서 Simulation Generates Hit Event를 체크해준다.

 

 

BlockCollisionActor 배치가 끝났다면 BlockCollisionActor와 충돌할 액터를 추가해준다. 모드 패널에서 구체 메시 하나를 BlockCollisionActor 위에 배치한다.

 

 

그 다음 배치한 구체의 모빌리티를 무버블로 하고, Physics 카테고리에서 Simulate Physics를 체크해준다.

 

 

다음 이미지와 같이 세팅이 모두 끝났다면 플레이 버튼을 눌러보자.

 

 

그러면 공이 떨어져서 상자에 맞는 순간 NotifyHit 로그가 출력되는 것을 볼 수 있다.

 

 

 

 

 

겹침 이벤트(Overlap Event)

 

겹침 이벤트는 겹침으로 설정된 오브젝트에 겹침이나 블록으로 설정된 다른 오브젝트가 겹쳐지면 발생하는 이벤트이다. 겹침 이벤트를 발생시키기 위해서는 Collision 카테고리에서 Generate Overlap Event를 true로 설정해줘야 한다.

 

겹침 이벤트를 처리할 클래스를 OverlapCollisionActor라는 이름으로 Actor 클래스를 상속해서 생성한다.

 

 

OverlapCollisionActor.h에 다음 멤버 변수와 함수 선언 코드를 추가한다.

 

protected:
    virtual void NotifyActorBeginOverlap(AActor *OtherActor) override;
    virtual void NotifyActorEndOverlap(AActor *OtherActor) override;

public:   
    UPROPERTY(EditAnywhere)
        class UStaticMeshComponent* BoxMesh;

 

NotifyActorBeginOverlap() 함수는 겹침이 시작되었을 때 실행되는 함수이고 NotifyActorEndOverlap() 함수는 겹침이 끝났을 때 실행되는 함수이다. 이 두함수를 통해서 우리는 언제 겹침이 시작되었는지, 언제 겹침이 끝났는지를 알 수 있다.

 

BoxMesh는 사실 큰 필요는 없지만 구체가 통과해서 지나갔음을 보여주기 위해서 추가한다. 하지만 만약 스태틱 메시를 사용하지 않을 것이라면 BoxComponent나 SphereComponent, CapsuleComponent 같은 콜리전 컴포넌트를 사용해야 한다.

 

그 다음엔 OverlapCollisionActor.cpp로 가서 스태틱 메시 컴포넌트를 사용하기 위해 다음 전처리기를 추가한다.

 

#include "Engine/Classes/Components/StaticMeshComponent.h"

 

AOverlapCollisionActor::AOverlapCollisionActor() 생성자 함수에 BoxMesh를 초기화하는 코드를 추가한다.

 

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

    BoxMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("BoxMesh"));
    RootComponent = BoxMesh;
}

 

그리고 NotifyActorBeginOverlap() 함수와 NotifyActorEndOverlap() 함수를 구현한다.

 

void AOverlapCollisionActor::NotifyActorBeginOverlap(AActor * OtherActor)
{
    UE_LOG(LogTemp, Log, TEXT("NotifyActorBeginOverlap"));
}

void AOverlapCollisionActor::NotifyActorEndOverlap(AActor * OtherActor)
{
    UE_LOG(LogTemp, Log, TEXT("NotifyActorEndOverlap"));
}

 

코드 수정이 끝나면 솔루션 탐색기에서 프로젝트를 빌드하고 에디터로 돌아가서 겹침 이벤트를 테스트하기 위한 작업을 한다.

 

우선 아까 전에 배치한 BlockCollisionActor보다 높은 공중에 구체가 통과해서 지나갈 수 있게 OverlapCollisionActor를 배치한다.

 

 

배치된 OverlapCollisionActor를 선택하고 디테일 패널에서 BoxMesh 컴포넌트를 선택한 다음에 비어있는 스태틱 메시에 모드에서 큐브 메시를 드래그 해서 할당해준다.

 

 

그 다음 Collision 카테고리에서 Generate Overlap Event를 체크해주고 Collision Preset을 OverlapAll로 설정한다.

 

 

마지막으로 구체를 선택한 다음 디테일 패널의 Collision 카테고리에서 Generate Overlap Event가 체크되어 있지 않다면 체크를 해준다. 겹침 이벤트가 발생하려면 겹치는 양 오브젝트에 모두 Generate Overlap Event가 true여야 한다.

 

 

플레이 버튼을 눌러보면 구체가 OverlapCollisionActor를 통과하면서 겹침이 시작되면 NotifyActorBeginOverlap 로그가 출력되고, 겹침이 끝나면 NotifyActorEndOverlap 로그가 출력되는 것을 확인할 수 있다.

 

 

반응형

+ Recent posts