안동민 개발노트

본문 시작

충돌 채널과 프로파일 설정

오브젝트·트레이스 채널과 충돌 프로파일의 Block·Overlap·Ignore 응답을 설계하고 적용합니다.

이전 장에서 우리는 언리얼 엔진의 월드와 씬을 구성하는 요소들, 그리고 C++와 블루프린트 간의 효율적인 협업 방식에 대해 알아보았습니다.

이제 게임플레이에서 가장 중요하고 빈번하게 발생하는 상호작용 중 하나인 충돌(Collision)에 대해 깊이 있게 다룰 시간입니다.

액터들이 서로 부딪히거나 겹쳤을 때 어떤 일이 발생할지 정의하는 것은 게임의 물리적 상호작용과 게임플레이 로직의 핵심입니다.

이를 위해 언리얼 엔진은 강력한 충돌 채널(Collision Channel)과 충돌 프로파일(Collision Profile) 시스템을 제공합니다.


충돌(Collision)이란 무엇인가요?

3D 게임에서 충돌은 두 개 이상의 오브젝트(액터 또는 컴포넌트)가 서로의 공간을 침범했을 때 발생하는 물리적인 접촉 또는 겹침 현상을 감지하는 것을 의미합니다.

언리얼 엔진은 이 충돌을 감지하고, 그 결과에 따라 다양한 반응을 일으킬 수 있도록 설계되어 있습니다.

충돌은 크게 두 가지 유형으로 나눌 수 있습니다.

  • 블록(Block): 충돌을 검사하는 이동·스윕이나 물리 접촉에서 통과를 막는 응답입니다. (예: 캐릭터가 벽에 부딪히는 것)
  • 오버랩(Overlap): 두 오브젝트가 서로의 공간을 침범했지만, 물리적으로 막지는 않고 겹쳤다는 사실만 감지하는 것입니다. (예: 플레이어가 아이템을 줍기 위해 아이템 위에 서는 것)

충돌 채널 (Collision Channel)

언리얼 엔진은 게임 내의 다양한 오브젝트들을 충돌 채널이라는 논리적인 그룹으로 분류합니다.

각 채널은 특정 유형의 오브젝트를 나타내며, 이 채널들을 사용하여 어떤 오브젝트가 다른 어떤 오브젝트와 충돌할지, 그리고 어떻게 반응할지 정의할 수 있습니다.

기본적으로 언리얼 엔진은 다음과 같은 내장 충돌 채널을 제공합니다.

  • WorldStatic: 움직이지 않는 월드 지오메트리 (벽, 바닥, 천장 등)
  • WorldDynamic: 움직이는 월드 오브젝트 (문, 엘리베이터 등)
  • Pawn: 플레이어 캐릭터나 AI 폰
  • PhysicsBody: 물리 시뮬레이션되는 오브젝트 (부서지는 상자 등)
  • Vehicle: 차량

CharacterMesh는 오브젝트 채널이 아니라 캐릭터 메시용 충돌 프로파일입니다. Visibility, Camera는 트레이스가 사용하는 채널이며 오브젝트 분류와 구별합니다.

커스텀 충돌 채널 생성

게임에 필요한 특정 유형의 오브젝트가 있다면, 직접 커스텀 충돌 채널을 생성할 수 있습니다.

예를 들어, 총알, 폭발 범위, 상호작용 오브젝트와 같은 채널을 만들 수 있습니다.

생성 방법

언리얼 에디터 메뉴에서 Edit > Project Settings를 엽니다.

왼쪽 패널에서 Engine > Collision을 선택합니다.

컴포넌트 분류를 만들 때는 New Object Channel, 트레이스 용도를 만들 때는 New Trace Channel을 선택합니다.

새로운 채널의 이름(예: Bullet, ExplosionArea)을 입력하고, 기본 반응(Default Response)을 Ignore, Overlap, Block 중 하나로 설정합니다.

  • Ignore: 기본적으로 이 채널의 모든 오브젝트를 무시합니다.
  • Overlap: 기본적으로 이 채널의 모든 오브젝트와 오버랩을 감지합니다.
  • Block: 기본적으로 이 채널의 모든 오브젝트를 블록합니다.

Accept를 클릭하여 채널을 생성합니다.

이렇게 생성된 커스텀 채널은 이제 게임의 모든 충돌 설정에서 사용할 수 있습니다.


충돌 프로파일 (Collision Profile)

충돌 프로파일은 특정 오브젝트가 다른 충돌 채널의 오브젝트들과 어떻게 상호작용할지(즉, Ignore, Overlap, Block 중 어떤 반응을 보일지)를 정의하는 사전 설정된 규칙들의 집합입니다.

충돌 프로파일을 사용하면 각 컴포넌트마다 일일이 충돌 반응을 설정하는 대신, 미리 정의된 프로파일을 적용하여 일관성과 효율성을 높일 수 있습니다.

충돌 프로파일 설정 방법

Project Settings > Collision 섹션에서 Collision Presets를 찾습니다.

언리얼 엔진은 BlockAll, OverlapAll, Pawn, PhysicsActor 등 여러 기본 프로파일을 제공합니다.

New Preset 버튼을 클릭하여 새로운 충돌 프로파일을 생성할 수 있습니다.

새 프로파일의 이름(예: PlayerWeapon, EnemyHitBox)을 지정하고 Collision Enabled, Object Type, 채널별 응답을 설정합니다.

가장 중요한 부분은 Collision Responses 섹션입니다.

여기서는 방금 만든 프로파일이 각 충돌 채널에 대해 어떤 반응을 보일지 설정합니다.

  • 예를 들어, EnemyHitBox와 Bullet을 별도의 오브젝트 채널로 먼저 만든 뒤 PlayerWeapon 프로파일을 설정한다면
    • Pawn 채널에 대해서는 Ignore (모든 Pawn 타입을 무시하며 자기 자신만 제외하는 설정은 아님)
    • WorldStatic 채널에 대해서는 Block (벽에 막힘)
    • EnemyHitBox 채널에 대해서는 Overlap (적의 히트박스와 겹칠 때 데미지 처리)
    • Bullet 채널에 대해서는 Ignore (총알은 총에 맞지 않음)
    • 등등, 게임의 논리에 맞게 각 채널에 대한 반응을 설정합니다.

액터/컴포넌트에 충돌 프로파일 적용

액터나 컴포넌트가 충돌을 감지하려면, 먼저 해당 액터/컴포넌트에 충돌 컴포넌트(Collision Component)가 부착되어 있어야 합니다. (예: UCapsuleComponent, UBoxComponent, USphereComponent, UStaticMeshComponent, USkeletalMeshComponent).

C++에서 적용

C++ 코드에서 충돌 컴포넌트를 생성하고 설정할 때, SetCollisionProfileName() 함수를 사용하여 미리 정의된 충돌 프로파일을 적용할 수 있습니다.

MyCharacter.cpp (생성자)
#include "MyCharacter.h"
#include "Components/CapsuleComponent.h" // UCapsuleComponent를 위해
#include "Components/SkeletalMeshComponent.h"

AMyCharacter::AMyCharacter()
{
    // ACharacter의 기본 루트 컴포넌트는 UCapsuleComponent입니다.
    UCapsuleComponent* CapsuleComp = GetCapsuleComponent();
    if (CapsuleComp)
    {
        // "Pawn" 충돌 프로파일 적용
        // 이 프로파일은 Project Settings -> Collision Preset에서 정의되어야 합니다.
        CapsuleComp->SetCollisionProfileName(TEXT("Pawn"));

        // 또는 직접 충돌 반응 설정 (프로파일 적용 대신)
        // CapsuleComp->SetCollisionEnabled(ECollisionEnabled::QueryAndPhysics); // 쿼리 및 물리 충돌 활성화
        // CapsuleComp->SetCollisionObjectType(ECollisionChannel::ECC_Pawn); // 이 컴포넌트의 오브젝트 타입 설정

        // 특정 채널에 대한 반응 설정 (예: Bullet 채널은 Block)
        // CapsuleComp->SetCollisionResponseToChannel(ECollisionChannel::ECC_GameTraceChannel1, ECollisionResponse::ECR_Block);
        // ECC_GameTraceChannel1은 Project Settings에서 정의한 커스텀 채널 (예: Bullet)
    }

    // 캐릭터의 메시 컴포넌트 (USkeletalMeshComponent)
    USkeletalMeshComponent* MeshComp = GetMesh();
    if (MeshComp)
    {
        // "CharacterMesh" 충돌 프로파일 적용
        MeshComp->SetCollisionProfileName(TEXT("CharacterMesh"));
        // MeshComp->SetCollisionEnabled(ECollisionEnabled::QueryOnly); // 트레이스·스윕·오버랩 쿼리 참여, 강체 시뮬레이션 제외
    }
}
  • SetCollisionProfileName(TEXT("ProfileName")): 가장 권장되는 방법입니다. Project Settings에서 정의한 충돌 프로파일을 적용합니다.
  • SetCollisionEnabled(): 충돌 감지 자체를 활성화/비활성화합니다.
    • NoCollision: 충돌 없음.
    • QueryOnly: 트레이스·스윕·오버랩 쿼리에 참여하며 강체 시뮬레이션에는 참여하지 않습니다. 스윕 이동의 Block 판정은 가능합니다.
    • PhysicsOnly: 강체 시뮬레이션에 참여하며 공간 쿼리에서는 제외됩니다.
    • QueryAndPhysics: 두 경로에 모두 참여합니다. 이 목록은 이 절에서 사용하는 기본 설정입니다.
  • SetCollisionObjectType(): 이 컴포넌트가 어떤 충돌 채널에 속하는지 정의합니다.
  • SetCollisionResponseToChannel(): 특정 채널에 대해 개별적인 반응을 설정할 때 사용합니다.

블루프린트에서 적용

블루프린트 클래스를 열고, 충돌 컴포넌트(예: CapsuleComponent, Mesh)를 선택한 후, 디테일 패널의 Collision 섹션에서 Collision Presets 드롭다운 메뉴를 통해 원하는 프로파일을 선택할 수 있습니다.

여기서 Custom을 선택하면 각 채널에 대한 반응을 수동으로 조절할 수도 있습니다.


충돌 이벤트 감지 (Overlap / Hit Events)

충돌이 발생했을 때 이를 감지하고 특정 로직을 실행하려면, 충돌 컴포넌트에서 이벤트를 활성화하고 해당 이벤트에 함수를 바인딩해야 합니다.

C++에서 이벤트 바인딩

MyTriggerVolume.h
#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "MyTriggerVolume.generated.h"

class UBoxComponent; // UBoxComponent를 미리 선언

UCLASS()
class MYPROJECT_API AMyTriggerVolume : public AActor
{
    GENERATED_BODY()

public:
    AMyTriggerVolume();

protected:
    virtual void BeginPlay() override;

    UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Collision")
    UBoxComponent* TriggerBox; // 트리거 볼륨 컴포넌트

    // 오버랩 시작 이벤트 함수
    UFUNCTION()
    void OnOverlapBegin(UPrimitiveComponent* OverlappedComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult);

    // 오버랩 종료 이벤트 함수
    UFUNCTION()
    void OnOverlapEnd(UPrimitiveComponent* OverlappedComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex);
};
MyTriggerVolume.cpp
#include "MyTriggerVolume.h"
#include "Components/BoxComponent.h" // UBoxComponent를 위해
#include "GameFramework/Pawn.h"

AMyTriggerVolume::AMyTriggerVolume()
{
    PrimaryActorTick.bCanEverTick = false;

    TriggerBox = CreateDefaultSubobject<UBoxComponent>(TEXT("TriggerBox"));
    RootComponent = TriggerBox; // 루트 컴포넌트로 설정

    // 충돌 프로파일 설정 (예: "OverlapAllDynamic" 또는 커스텀 프로파일)
    TriggerBox->SetCollisionProfileName(TEXT("OverlapAllDynamic"));

    // 오버랩 이벤트 활성화
    TriggerBox->SetGenerateOverlapEvents(true);

    // BeginPlay에서 이벤트 바인딩
    // TriggerBox->OnComponentBeginOverlap.AddDynamic(this, &AMyTriggerVolume::OnOverlapBegin);
    // TriggerBox->OnComponentEndOverlap.AddDynamic(this, &AMyTriggerVolume::OnOverlapEnd);
}

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

    // 이 예제는 BeginPlay 이후의 이벤트를 구독합니다.
    // 바인딩 전에 이미 성립한 겹침을 이 코드가 다시 통지하지는 않습니다.
    TriggerBox->OnComponentBeginOverlap.AddDynamic(this, &AMyTriggerVolume::OnOverlapBegin);
    TriggerBox->OnComponentEndOverlap.AddDynamic(this, &AMyTriggerVolume::OnOverlapEnd);
}

void AMyTriggerVolume::OnOverlapBegin(UPrimitiveComponent* OverlappedComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
{
    // 자신과 겹친 액터가 Pawn인지 확인 (플레이어 및 AI 포함)
    if (OtherActor && OtherActor != this && OtherActor->IsA(APawn::StaticClass()))
    {
        UE_LOG(LogTemp, Warning, TEXT("Pawn entered trigger volume!"));
        // 여기에 게임플레이 로직 구현 (예: 아이템 획득, 문 열기 등)
    }
}

void AMyTriggerVolume::OnOverlapEnd(UPrimitiveComponent* OverlappedComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex)
{
    if (OtherActor && OtherActor != this && OtherActor->IsA(APawn::StaticClass()))
    {
        UE_LOG(LogTemp, Warning, TEXT("Pawn exited trigger volume!"));
    }
}
  • SetGenerateOverlapEvents(true): 해당 컴포넌트가 오버랩 이벤트를 발생시키도록 설정합니다.
  • OnComponentBeginOverlap / OnComponentHit: 언리얼 엔진의 Delegate 시스템입니다. AddDynamic() 함수를 사용하여 특정 함수를 이 델리게이트에 바인딩함으로써 이벤트가 발생했을 때 해당 함수가 호출되도록 합니다. 바인딩할 함수는 반드시 UFUNCTION()으로 선언되어야 합니다.
  • OnComponentHit: 물리적인 블록 충돌이 발생했을 때 호출되는 델리게이트입니다. OnComponentBeginOverlap과 유사한 방식으로 바인딩하여 사용합니다.
응답 조합과 이벤트 조건

두 컴포넌트의 상호 응답과 추가 알림 조건을 구분합니다.

응답 조합과 이벤트 조건
상호 응답결과이벤트를 위한 추가 조건
한쪽이라도 Ignore이 쌍의 상호작용 무시Overlap·Hit 콜백 대상으로 삼지 않음
Overlap + Overlap 또는 Block겹침으로 처리쿼리 활성화와 양쪽 GenerateOverlapEvents, 올바른 콜백 연결
Block + Block막힘으로 처리실제 스윕 이동 또는 물리 접촉이 필요. 물리 시뮬레이션 Hit 알림은 보고할 컴포넌트의 설정도 필요
한쪽이라도 Ignore
결과: 이 쌍의 상호작용 무시
이벤트를 위한 추가 조건: Overlap·Hit 콜백 대상으로 삼지 않음
Overlap + Overlap 또는 Block
결과: 겹침으로 처리
이벤트를 위한 추가 조건: 쿼리 활성화와 양쪽 GenerateOverlapEvents, 올바른 콜백 연결
Block + Block
결과: 막힘으로 처리
이벤트를 위한 추가 조건: 실제 스윕 이동 또는 물리 접촉이 필요. 물리 시뮬레이션 Hit 알림은 보고할 컴포넌트의 설정도 필요

프리셋 이름보다 런타임의 두 컴포넌트 설정을 확인합니다. 응답이 맞아도 콜백을 구독하기 전의 사건을 재생하지는 않습니다.


이제 언리얼 엔진의 충돌 채널과 프로파일 시스템을 이해하고, 이를 통해 액터 간의 충돌 상호작용을 어떻게 정의하고 감지하는지 파악하셨을 것입니다.

이 시스템은 게임의 물리적 상호작용을 구현하는 데 있어 매우 유연하고 강력한 기반을 제공합니다.