충돌 채널과 프로파일 설정
이전 장에서 우리는 언리얼 엔진의 월드와 씬을 구성하는 요소들, 그리고 C++와 블루프린트 간의 효율적인 협업 방식에 대해 알아보았습니다. 이제 게임플레이에서 가장 중요하고 빈번하게 발생하는 상호작용 중 하나인 충돌(Collision)에 대해 깊이 있게 다룰 시간입니다. 액터들이 서로 부딪히거나 겹쳤을 때 어떤 일이 발생할지 정의하는 것은 게임의 물리적 상호작용과 게임플레이 로직의 핵심입니다. 이를 위해 언리얼 엔진은 강력한 충돌 채널(Collision Channel)과 충돌 프로파일(Collision Profile) 시스템을 제공합니다.
충돌(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)을 지정하고, Type을 Block 또는 Overlap으로 설정합니다.
가장 중요한 부분은 Collision Responses 섹션입니다. 여기서는 방금 만든 프로파일이 각 충돌 채널에 대해 어떤 반응을 보일지 설정합니다.
- 예를 들어,
PlayerWeapon프로파일을 만들었다면Pawn채널에 대해서는Ignore(자신과 충돌하지 않음)WorldStatic채널에 대해서는Block(벽에 막힘)EnemyHitBox채널에 대해서는Overlap(적의 히트박스와 겹칠 때 데미지 처리)Bullet채널에 대해서는Ignore(총알은 총에 맞지 않음)- 등등, 게임의 논리에 맞게 각 채널에 대한 반응을 설정합니다.
액터/컴포넌트에 충돌 프로파일 적용
액터나 컴포넌트가 충돌을 감지하려면, 먼저 해당 액터/컴포넌트에 충돌 컴포넌트(Collision Component)가 부착되어 있어야 합니다. (예: UCapsuleComponent, UBoxComponent, USphereComponent, UStaticMeshComponent, USkeletalMeshComponent).
C++에서 적용
C++ 코드에서 충돌 컴포넌트를 생성하고 설정할 때, SetCollisionProfileName() 함수를 사용하여 미리 정의된 충돌 프로파일을 적용할 수 있습니다.
#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)
아래 다이어그램은 이 절의 핵심 흐름을 역할과 상태 전환 중심으로 정리한 것입니다.
충돌이 발생했을 때 이를 감지하고 특정 로직을 실행하려면, 충돌 컴포넌트에서 이벤트를 활성화하고 해당 이벤트에 함수를 바인딩해야 합니다.
C++에서 이벤트 바인딩
#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);
};#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과 유사한 방식으로 바인딩하여 사용합니다.
충돌이 예상대로 감지되지 않을 때는 코드만 보기보다, 채널 분류부터 프로파일, 반응표, 이벤트 플래그까지 같은 순서로 되짚는 것이 빠릅니다.
이제 언리얼 엔진의 충돌 채널과 프로파일 시스템을 이해하고, 이를 통해 액터 간의 충돌 상호작용을 어떻게 정의하고 감지하는지 파악하셨을 것입니다. 이 시스템은 게임의 물리적 상호작용을 구현하는 데 있어 매우 유연하고 강력한 기반을 제공합니다.