본문으로 건너뛰기

안동민 개발노트

본문 시작

충돌 채널과 프로파일 설정

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

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

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

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

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

채널은 대상을 분류하고, 프로파일은 반응표를 묶는다

충돌 설정은 “이 컴포넌트가 무엇인지”와 “상대 채널에 어떻게 반응할지”를 함께 정하는 작업입니다. 프로파일을 쓰면 C++과 에디터에서 같은 규칙을 반복 없이 적용할 수 있습니다.

  1. Object Channel

    컴포넌트 자신이 어떤 종류의 오브젝트인지 정합니다. Pawn, WorldStatic, PhysicsBody가 여기에 해당합니다.

  2. Trace Channel

    라인 트레이스나 스윕처럼 “검사 광선”이 어떤 대상을 볼지 정하는 쿼리용 분류입니다.

  3. Response

    상대 채널마다 Block, Overlap, Ignore 중 하나로 실제 반응을 결정합니다.

  4. Profile

    오브젝트 타입과 반응표를 이름으로 저장해 코드와 에디터에서 같은 규칙을 재사용합니다.

  5. 설계 순서

    먼저 게임플레이 대상군을 채널로 나누고, 상호작용 규칙을 표로 적은 뒤 프로파일로 고정합니다.

  6. C++ 적용

    생성자에서 컴포넌트를 만들고 프로파일 이름을 적용하면 기본 충돌 규칙이 한 줄로 정리됩니다.

  7. 디버그 기준

    충돌이 안 잡히면 컴포넌트 활성화, 오브젝트 타입, 상대 채널 반응을 순서대로 확인합니다.


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

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

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

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

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

충돌 채널 (Collision Channel)

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

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

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

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

커스텀 충돌 채널 생성

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

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

생성 방법

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

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

New Collision 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)을 지정하고, TypeBlock 또는 Overlap으로 설정합니다.

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

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

  • 예를 들어, PlayerWeapon 프로파일을 만들었다면
    • Pawn 채널에 대해서는 Ignore (자신과 충돌하지 않음)
    • WorldStatic 채널에 대해서는 Block (벽에 막힘)
    • EnemyHitBox 채널에 대해서는 Overlap (적의 히트박스와 겹칠 때 데미지 처리)
    • Bullet 채널에 대해서는 Ignore (총알은 총에 맞지 않음)
    • 등등, 게임의 논리에 맞게 각 채널에 대한 반응을 설정합니다.

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

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

C++에서 적용

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

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

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: 오버랩/히트 감지(쿼리)만 가능, 물리적 블록은 안 함.
    • PhysicsOnly: 물리적 블록만 가능, 오버랩/히트 쿼리는 안 함.
    • QueryAndPhysics: 오버랩/히트 쿼리 및 물리적 블록 모두 가능.
  • SetCollisionObjectType(): 이 컴포넌트가 어떤 충돌 채널에 속하는지 정의합니다.
  • SetCollisionResponseToChannel(): 특정 채널에 대해 개별적인 반응을 설정할 때 사용합니다.

블루프린트에서 적용

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

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


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

Overlap과 Hit은 컴포넌트 설정, 이벤트 생성, 델리게이트, 시그니처가 맞아야 호출된다

코드가 맞아도 충돌 설정이 꺼져 있으면 이벤트는 오지 않는다.

조건확인할 것흔한 실패
Component충돌을 받을 컴포넌트와 채널 응답을 정한다실제 겹치는 컴포넌트가 다르다
Generate EventsOverlap 또는 Hit 관련 플래그를 켠다이벤트 생성 옵션이 한쪽에서 꺼져 있다
Delegate생성자나 BeginPlay에서 AddDynamic으로 묶는다중복 바인딩 또는 바인딩 누락
SignatureUFUNCTION과 콜백 인자가 정확히 맞다함수는 있지만 델리게이트와 시그니처가 다르다

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

C++에서 이벤트 바인딩

AMyTriggerVolume.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);
};
AMyTriggerVolume.cpp
#include "MyTriggerVolume.h"
#include "Components/BoxComponent.h" // UBoxComponent를 위해

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)
{
    // 자신과 겹친 액터가 플레이어인지 확인 (예시)
    if (OtherActor && OtherActor != this && OtherActor->IsA(APawn::StaticClass()))
    {
        UE_LOG(LogTemp, Warning, TEXT("Player 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("Player exited trigger volume!"));
    }
}
  • SetGenerateOverlapEvents(true): 해당 컴포넌트가 오버랩 이벤트를 발생시키도록 설정합니다.
  • OnComponentBeginOverlap / OnComponentHit: 언리얼 엔진의 Delegate 시스템입니다. AddDynamic() 함수를 사용하여 특정 함수를 이 델리게이트에 바인딩함으로써 이벤트가 발생했을 때 해당 함수가 호출되도록 합니다. 바인딩할 함수는 반드시 UFUNCTION()으로 선언되어야 합니다.
  • OnComponentHit: 물리적인 블록 충돌이 발생했을 때 호출되는 델리게이트입니다. OnComponentBeginOverlap과 유사한 방식으로 바인딩하여 사용합니다.

충돌이 예상대로 감지되지 않을 때는 코드만 보기보다, 채널 분류부터 프로파일, 반응표, 이벤트 플래그까지 같은 순서로 되짚는 것이 빠릅니다.

콜백보다 두 컴포넌트의 충돌 결과를 먼저 본다

Overlap·Hit은 양쪽 Object Type과 Response가 만든 유효 결과에서 시작한다.

  1. 원하는 이벤트의 추가 조건

    EVENT OVERLAP query 가능한 Enabled 결과: Overlap 양쪽 GenerateOverlapEvents HIT 결과: Block 실제 이동·물리 접촉 보고 측 Simulation Hit Events

  2. BeginOverlap

    OVERLAP query 가능한 Enabled 결과: Overlap 양쪽 GenerateOverlapEvents

  3. ComponentHit

    HIT 결과: Block 실제 이동·물리 접촉 보고 측 Simulation Hit Events

  4. Enabled + runtime Profile

    ENABLED

  5. ENABLED
  6. A ↔ B Response

    PAIR

  7. Overlap / Hit flags

    FLAG

  8. UFUNCTION + AddDynamic

    BIND

A \ BIgnoreOverlapBlock
IgnoreIgnoreIgnoreIgnore
OverlapIgnoreOverlapOverlap
BlockIgnoreOverlapBlock

아래 다이어그램은 충돌 채널, 프로파일, 반응 결과, 이벤트 조건을 한 번에 점검하도록 정리한 것입니다.

이벤트 함수는 양쪽 충돌 설정을 통과한 마지막 게이트다

최종 상호작용은 A와 B의 Collision Enabled, Object Type, 상대 채널 Response를 함께 계산해 정해진다. Block·Overlap 결과가 나온 뒤에야 notification flag와 delegate binding을 확인한다.

  1. query + 양쪽 opt-in

    OVERLAP 최종 response가 Overlap 양쪽 Generate Overlap Events 활성 Begin/End delegate에 handler binding

  2. block + notification

    HIT 최종 response가 Block 실제 movement 또는 physics contact 발생 physics simulation 알림은 listener의 Simulation Generates Hit Events 활성

Overlap이나 Hit 이벤트가 호출되지 않을 때는 이벤트 함수보다 충돌 활성화, 채널 반응, 이벤트 플래그, 바인딩 시점을 먼저 확인해야 합니다.

충돌은 채널, 프로파일, Overlap, Hit의 상호작용 규칙이다

한쪽 설정만 보면 안 되고 두 객체의 채널과 응답이 서로 합의하는지 봐야 한다.

역할확인 기준
ChannelObject Channel과 Trace Channel로 감지 기준을 만든다누가 누구를 감지하는지 방향이 분명하다
ProfileBlock, Overlap, Ignore 조합을 이름으로 묶는다컴포넌트마다 같은 규칙을 재사용한다
Overlap트리거, 아이템, 감지 영역처럼 통과 감지가 필요하다Generate Overlap Events가 켜져 있다
Hit물리 충돌이나 막힘 결과가 필요하다Block 응답과 Hit 이벤트 조건이 맞다

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

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