본문 바로가기

라인 트레이스 (Trace) 시스템

시작점·끝점·채널을 지정한 Line Trace로 대상을 검출하고 FHitResult에서 충돌 정보를 읽습니다.

이전 절에서 우리는 물리 시뮬레이션과 오브젝트에 힘을 적용하는 방법을 배웠습니다.

이제 직접적인 충돌이나 오버랩 감지 없이도 게임 월드 내의 오브젝트를 탐색하고 정보를 얻는 강력한 방법인 라인 트레이스(Line Trace) 시스템에 대해 알아보겠습니다.

라인 트레이스는 레이캐스트(Raycast)라고도 불리며, 가상의 선을 쏘아 그 선이 어떤 오브젝트와 부딪혔는지 감지하는 데 사용됩니다.


라인 트레이스란 무엇인가요?

라인 트레이스(Line Trace)는 3D 공간의 시작 지점에서 종료 지점까지 가상의 선(혹은 광선)을 발사하여, 그 선이 월드 내의 어떤 오브젝트와 교차하는지 감지하는 쿼리(Query) 시스템입니다.

충돌 컴포넌트 간의 물리적 접촉이나 겹침을 기다리는 대신, 능동적으로 월드를 "스캔"하여 정보를 얻는 방식입니다.

라인 트레이스는 다음과 같은 다양한 게임플레이 상황에서 활용됩니다.

  • 총알/투사체 히트 감지: 발사 순간의 경로를 검사하는 히트스캔 판정에 사용합니다. 실제 투사체의 이동 시간·부피를 재현하지는 않으며, 빠른 투사체는 스윕·연속 충돌 검사 등 별도의 설계가 필요합니다.
  • 레이저 시야/타겟팅: 플레이어가 보고 있는 정확한 지점이나 오브젝트를 식별합니다.
  • AI 시야: AI 캐릭터가 전방에 장애물이 있는지, 플레이어를 볼 수 있는지 등을 판단합니다.
  • 상호작용: 플레이어가 특정 오브젝트(버튼, 문 등)를 바라보고 있을 때만 상호작용 가능하도록 감지합니다.
  • 지면 감지: 캐릭터가 점프 후 착지할 때 지면의 특성(재질, 높이)을 파악합니다.
  • 벽 타고 움직이기: 캐릭터가 벽에 붙어 있을 때 벽면의 노멀(법선) 벡터를 얻어 벽을 따라 움직이게 합니다.

트레이스의 유형

언리얼 엔진은 다양한 형태의 트레이스 함수를 제공하며, 목적에 따라 적절한 함수를 선택해야 합니다.

  • Line Trace (라인 트레이스): 가장 기본적인 형태. 점과 점 사이의 직선을 따라 충돌을 감지합니다.
  • Sphere Trace (스피어 트레이스): 점과 점 사이의 경로를 따라 구체를 굴리듯이 충돌을 감지합니다. 총알처럼 얇은 오브젝트가 아닌, 더 넓은 범위의 감지가 필요할 때 유용합니다.
  • Box Trace (박스 트레이스): 점과 점 사이의 경로를 따라 직육면체를 움직이듯이 충돌을 감지합니다. 넓은 면적의 장애물 감지에 좋습니다.
  • Capsule Trace (캡슐 트레이스): 점과 점 사이의 경로를 따라 캡슐 형태를 움직이듯이 충돌을 감지합니다. 캐릭터 이동 시 장애물이나 지면 감지에 사용하기 좋습니다.

필터는 대표적으로 다음 두 방식으로 선택합니다. 프로파일 기반 함수도 있으므로 사용할 오버로드의 계약을 확인합니다.

  • By Channel (채널별 트레이스): 특정 충돌 채널(Collision Channel)에 대해서만 충돌을 감지합니다. (예: ECC_Visibility 또는 커스텀 Bullet 채널)
  • By Object Type (오브젝트 타입별 트레이스): 특정 오브젝트 타입(Object Type)에 대해서만 충돌을 감지합니다. (예: WorldStatic, Pawn, PhysicsBody 등)

또한, 단일 히트만 감지하는 Single 버전과 여러 히트를 감지하는 Multi 버전이 있습니다.

트레이스의 결과 배열과 반환 bool을 따로 읽습니다

0..1000 cm 가정에서 100 cm의 A Overlap을 지나 300 cm의 벽을 첫 Block으로 반환하고, 700 cm의 B는 수집하지 않는 선택된 조회 경로이다. 원 FireWeapon의 10000 cm와 구분하고 내부 탐색 구현 순서를 단정하지 않는다.

UNREAL C++ · CH5-4

트레이스의 결과 배열과 반환 bool을 따로 읽습니다

Single·Multi 및 Channel·Object Type마다 필터와 반환 계약이 다릅니다. 본문의 실제 FireWeapon 코드는 Single By Channel만 호출합니다.

Single By Channel은 첫 Block을 결과로 반환한다시작X0cm,길이1000cm,+X방향의가정에서A는100cmOverlap,벽은300cmBlock,B는700cmBlock이다. A에서계속검사한뒤첫Block벽을Single결과로반환한다. 벽뒤B는이결과에들어오지않으며B로향하는간선도없다. Multi반환배열과bool은아래표및본문의별도계약으로비교한다.쿼리 시작0 → 1000 cmA100 cm · Overlap벽300 cm · BlockSingle 결과벽 · bool=true벽 뒤 · 미수집B700 cm · Block
Single By Channel은 첫 Block을 결과로 반환한다시작X0cm,길이1000cm,+X방향의가정에서A는100cmOverlap,벽은300cmBlock,B는700cmBlock이다. A에서계속검사한뒤첫Block벽을Single결과로반환한다. 벽뒤B는이결과에들어오지않으며B로향하는간선도없다. Multi반환배열과bool은아래표및본문의별도계약으로비교한다.쿼리 시작0 → 1000 cmA100 cm · Overlap벽300 cm · BlockSingle 결과벽 · bool=true벽 뒤 · 미수집B700 cm · Block

선은 이 가정의 Single 검사와 반환 흐름입니다. B를 별도 영역에 두어 첫 Block 뒤의 대상까지 수집한 결과로 읽지 않게 했습니다. 실제 원 FireWeapon의 기본 거리는 10000 cm이며 이 그림의 1000 cm 가정과 다릅니다.

트레이스 필터와 반환 범위
선택결과 범위읽을 때의 경계
Single By Channel지정 채널의 첫 Blocking Hittrue는 blocking hit 발견. Overlap만 있는 대상은 이 결과로 얻지 않음
Multi By Channel첫 Block까지의 Overlap과 그 BlockBlock 뒤를 관통해 모두 수집하지 않음. bool은 Block 유무이므로 false여도 Overlap 배열이 있을 수 있음
Multi By Object Type요청한 타입에 속한 쿼리 대상들타입 필터를 명시하며, 채널 Multi의 첫 Block 중단 규칙과 구별
Single By Channel
결과 범위: 지정 채널의 첫 Blocking Hit
읽을 때의 경계: true는 blocking hit 발견. Overlap만 있는 대상은 이 결과로 얻지 않음
Multi By Channel
결과 범위: 첫 Block까지의 Overlap과 그 Block
읽을 때의 경계: Block 뒤를 관통해 모두 수집하지 않음. bool은 Block 유무이므로 false여도 Overlap 배열이 있을 수 있음
Multi By Object Type
결과 범위: 요청한 타입에 속한 쿼리 대상들
읽을 때의 경계: 타입 필터를 명시하며, 채널 Multi의 첫 Block 중단 규칙과 구별

계약 예시 · Channel Multi, Overlap만 발견

Overlap 결과 배열이 있어도 Blocking Hit가 없으면 bool=false입니다.

계약 예시 · Channel Multi, Block도 발견

그 앞의 Overlap들과 첫 Block을 반환하며 bool=true입니다. 그 Block 뒤의 대상을 모두 수집하는 호출은 아닙니다.

다른 행은 API 계약 비교이며 실제 다중 히트 실행 결과가 아닙니다. 이 예제의 시작점은 Pawn의 EyesViewPoint이고 FollowCamera와 같다고 가정하지 않습니다. 자기 자신 제외·충돌 형상·쿼리 참여를 함께 확인합니다.

이 예의 조건

  • 본문과 원 도표에 제시된 사례의 입력·조건을 사용합니다. 설명용 수치나 독립 비교 경로는 각 단계에 표시합니다.
  • 현재 상태·값과 전환 근거의 위치는 모든 단계에서 같습니다. 조건이 맞지 않거나 실행되지 않은 경로를 성공한 동작으로 해석하지 않습니다.
관계도의 보충 설명
원 도표의 제목·노드·관계·조건·주석
범위원문
관계·조건 설명시작 X 0 cm, 길이 1000 cm, +X 방향의 가정에서 A는 100 cm Overlap, 벽은 300 cm Block, B는 700 cm Block이다. A에서 계속 검사한 뒤 첫 Block 벽을 Single 결과로 반환한다. 벽 뒤 B는 이 결과에 들어오지 않으며 B로 향하는 간선도 없다. Multi 반환 배열과 bool은 아래 표 및 본문의 별도 계약으로 비교한다.
예의 값과 변화
관찰·상황값·보충 정보변화·이유
조회 가정

설명용 0..1000 cm에 대상 응답을 둔다.

  • A: 100 cm Overlap
  • 벽: 300 cm Block
  • 원 FireWeapon의 10000 cm 코드와 별도 설명 사례임을 명시한다.
반환 경계

이 query는 첫 Block 벽까지의 결과를 정한다.

  • 첫 Block: 벽 300 cm
  • OverlapA: Block 아님
  • 간선은 논리 반환 범위이며, 엔진 내부 탐색 순서를 보장하지 않는다.
뒤 대상 제외

벽 뒤 B의 700 cm는 이 반환 범위에 수집되지 않는다.

  • B: 700 cm 미수집
  • 종료 범위: 벽까지
  • 벽을 통과하는 피해 권한을 이 조회 결과에 추가하지 않는다.

트레이스의 결과 배열과 반환 bool을 따로 읽습니다

0..1000 cm 가정에서 100 cm의 A Overlap을 지나 300 cm의 벽을 첫 Block으로 반환하고, 700 cm의 B는 수집하지 않는 선택된 조회 경로이다. 원 FireWeapon의 10000 cm와 구분하고 내부 탐색 구현 순서를 단정하지 않는다.

UNREAL C++ · CH5-4

트레이스의 결과 배열과 반환 bool을 따로 읽습니다

Single·Multi 및 Channel·Object Type마다 필터와 반환 계약이 다릅니다. 본문의 실제 FireWeapon 코드는 Single By Channel만 호출합니다.

Single By Channel은 첫 Block을 결과로 반환한다시작X0cm,길이1000cm,+X방향의가정에서A는100cmOverlap,벽은300cmBlock,B는700cmBlock이다. A에서계속검사한뒤첫Block벽을Single결과로반환한다. 벽뒤B는이결과에들어오지않으며B로향하는간선도없다. Multi반환배열과bool은아래표및본문의별도계약으로비교한다.쿼리 시작0 → 1000 cmA100 cm · Overlap벽300 cm · BlockSingle 결과벽 · bool=true벽 뒤 · 미수집B700 cm · Block
Single By Channel은 첫 Block을 결과로 반환한다시작X0cm,길이1000cm,+X방향의가정에서A는100cmOverlap,벽은300cmBlock,B는700cmBlock이다. A에서계속검사한뒤첫Block벽을Single결과로반환한다. 벽뒤B는이결과에들어오지않으며B로향하는간선도없다. Multi반환배열과bool은아래표및본문의별도계약으로비교한다.쿼리 시작0 → 1000 cmA100 cm · Overlap벽300 cm · BlockSingle 결과벽 · bool=true벽 뒤 · 미수집B700 cm · Block

선은 이 가정의 Single 검사와 반환 흐름입니다. B를 별도 영역에 두어 첫 Block 뒤의 대상까지 수집한 결과로 읽지 않게 했습니다. 실제 원 FireWeapon의 기본 거리는 10000 cm이며 이 그림의 1000 cm 가정과 다릅니다.

트레이스 필터와 반환 범위
선택결과 범위읽을 때의 경계
Single By Channel지정 채널의 첫 Blocking Hittrue는 blocking hit 발견. Overlap만 있는 대상은 이 결과로 얻지 않음
Multi By Channel첫 Block까지의 Overlap과 그 BlockBlock 뒤를 관통해 모두 수집하지 않음. bool은 Block 유무이므로 false여도 Overlap 배열이 있을 수 있음
Multi By Object Type요청한 타입에 속한 쿼리 대상들타입 필터를 명시하며, 채널 Multi의 첫 Block 중단 규칙과 구별
Single By Channel
결과 범위: 지정 채널의 첫 Blocking Hit
읽을 때의 경계: true는 blocking hit 발견. Overlap만 있는 대상은 이 결과로 얻지 않음
Multi By Channel
결과 범위: 첫 Block까지의 Overlap과 그 Block
읽을 때의 경계: Block 뒤를 관통해 모두 수집하지 않음. bool은 Block 유무이므로 false여도 Overlap 배열이 있을 수 있음
Multi By Object Type
결과 범위: 요청한 타입에 속한 쿼리 대상들
읽을 때의 경계: 타입 필터를 명시하며, 채널 Multi의 첫 Block 중단 규칙과 구별

계약 예시 · Channel Multi, Overlap만 발견

Overlap 결과 배열이 있어도 Blocking Hit가 없으면 bool=false입니다.

계약 예시 · Channel Multi, Block도 발견

그 앞의 Overlap들과 첫 Block을 반환하며 bool=true입니다. 그 Block 뒤의 대상을 모두 수집하는 호출은 아닙니다.

다른 행은 API 계약 비교이며 실제 다중 히트 실행 결과가 아닙니다. 이 예제의 시작점은 Pawn의 EyesViewPoint이고 FollowCamera와 같다고 가정하지 않습니다. 자기 자신 제외·충돌 형상·쿼리 참여를 함께 확인합니다.

이 예의 조건

  • 본문과 원 도표에 제시된 사례의 입력·조건을 사용합니다. 설명용 수치나 독립 비교 경로는 각 단계에 표시합니다.
  • 현재 상태·값과 전환 근거의 위치는 모든 단계에서 같습니다. 조건이 맞지 않거나 실행되지 않은 경로를 성공한 동작으로 해석하지 않습니다.

관계도의 보충 설명

원 도표의 제목·노드·관계·조건·주석
범위원문
관계·조건 설명시작 X 0 cm, 길이 1000 cm, +X 방향의 가정에서 A는 100 cm Overlap, 벽은 300 cm Block, B는 700 cm Block이다. A에서 계속 검사한 뒤 첫 Block 벽을 Single 결과로 반환한다. 벽 뒤 B는 이 결과에 들어오지 않으며 B로 향하는 간선도 없다. Multi 반환 배열과 bool은 아래 표 및 본문의 별도 계약으로 비교한다.
예의 값과 변화
관찰·상황값·보충 정보변화·이유
조회 가정

설명용 0..1000 cm에 대상 응답을 둔다.

  • A: 100 cm Overlap
  • 벽: 300 cm Block
  • 원 FireWeapon의 10000 cm 코드와 별도 설명 사례임을 명시한다.
반환 경계

이 query는 첫 Block 벽까지의 결과를 정한다.

  • 첫 Block: 벽 300 cm
  • OverlapA: Block 아님
  • 간선은 논리 반환 범위이며, 엔진 내부 탐색 순서를 보장하지 않는다.
뒤 대상 제외

벽 뒤 B의 700 cm는 이 반환 범위에 수집되지 않는다.

  • B: 700 cm 미수집
  • 종료 범위: 벽까지
  • 벽을 통과하는 피해 권한을 이 조회 결과에 추가하지 않는다.

C++에서 라인 트레이스 구현하기

라인 트레이스 함수들은 주로 UWorld 클래스와 UKismetSystemLibrary (블루프린트 함수 라이브러리)에 정의되어 있습니다.

C++에서는 UWorld 포인터를 통해 호출하는 것이 일반적입니다.

MyCharacter.h (예시: 캐릭터가 총을 쏘는 함수)
#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Character.h"
#include "MyCharacter.generated.h"

UCLASS()
class MYPROJECT_API AMyCharacter : public ACharacter
{
    GENERATED_BODY()

public:
    AMyCharacter();

protected:
    virtual void BeginPlay() override;

public:
    // 마우스 왼쪽 클릭 시 발사되는 함수 (블루프린트에서 호출 가능하도록)
    UFUNCTION(BlueprintCallable, Category = "Combat")
    void FireWeapon();

    // 트레이스 길이를 에디터에서 조절할 수 있도록 노출
    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Combat")
    float TraceDistance = 10000.0f; // 100미터
};
MyCharacter.cpp
#include "MyCharacter.h"
#include "Components/CapsuleComponent.h"
#include "GameFramework/SpringArmComponent.h" // 카메라 암 컴포넌트
#include "Camera/CameraComponent.h"         // 카메라 컴포넌트
#include "Kismet/KismetMathLibrary.h"       // Rotator To Vector 등을 위해 (선택 사항)
#include "DrawDebugHelpers.h"               // 디버그 드로잉을 위해
#include "Engine/World.h"
#include "CollisionQueryParams.h"

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

    // ... 기존 컴포넌트 설정 (CapsuleComponent, Mesh, SpringArm, Camera 등) ...
}

void AMyCharacter::BeginPlay()
{
    Super::BeginPlay();
}

void AMyCharacter::FireWeapon()
{
    // 월드 포인터 확인
    UWorld* World = GetWorld();
    if (!World)
    {
        UE_LOG(LogTemp, Error, TEXT("World is null. Cannot perform trace."));
        return;
    }

    // 1. Pawn의 눈 위치와 시야 방향을 시작 기준으로 사용
    FVector StartLocation;
    FRotator CameraRotation;
    GetActorEyesViewPoint(StartLocation, CameraRotation);
    // 또는 ACharacter의 EyeHeight 등을 사용할 수 있습니다.
    // FVector StartLocation = GetMesh()->GetSocketLocation(TEXT("MuzzleSocket")); // 총구 소켓이 있다면

    // 2. 시야 방향과 사거리로 종료 지점 결정
    FVector EndLocation = StartLocation + (CameraRotation.Vector() * TraceDistance);

    // 3. 트레이스 파라미터 설정
    FCollisionQueryParams TraceParams;
    TraceParams.AddIgnoredActor(this); // 트레이스 시 자기 자신(캐릭터)은 무시
    TraceParams.bTraceComplex = true;  // 복잡 충돌 쿼리 요청; 실제 형상은 에셋의 Collision Complexity에도 따름
    TraceParams.bReturnPhysicalMaterial = false; // 물리 재질 정보 반환 여부

    // 4. 충돌 결과 정보 구조체
    FHitResult HitResult;

    // 5. 라인 트레이스 실행!
    // LineTraceSingleByChannel(히트 결과, 시작점, 끝점, 충돌 채널, 쿼리 파라미터)
    // ECC_Visibility는 Project Settings의 Collision -> Trace Channels에서 기본으로 정의된 채널
    bool bHit = World->LineTraceSingleByChannel(HitResult, StartLocation, EndLocation, ECollisionChannel::ECC_Visibility, TraceParams);

    // 6. 트레이스 결과 처리
    if (bHit)
    {
        // 뭔가에 맞았다!
        UE_LOG(LogTemp, Warning, TEXT("Trace Hit: %s at %s"), *GetNameSafe(HitResult.GetActor()), *HitResult.Location.ToString());

        // 히트한 액터, 컴포넌트, 위치, 노멀 벡터 등의 정보에 접근
        AActor* HitActor = HitResult.GetActor();
        UPrimitiveComponent* HitComponent = HitResult.GetComponent();
        FVector HitLocation = HitResult.Location;
        FVector HitNormal = HitResult.Normal;

        // 여기에 게임플레이 로직 구현 (예: 데미지 적용, 파티클 생성 등)
        if (HitActor)
        {
            // 예시: 맞은 액터에게 데미지 적용 (추후 데미지 시스템 학습)
            // UGameplayStatics::ApplyDamage(HitActor, 10.0f, GetController(), this, UDamageType::StaticClass());
        }
    }
    else
    {
        // 아무것도 맞지 않았다
        UE_LOG(LogTemp, Warning, TEXT("Trace Missed."));
    }

    // 7. 디버그 드로잉 (개발 중에 트레이스 시각화)
    DrawDebugLine(World, StartLocation, EndLocation, bHit ? FColor::Red : FColor::Green, false, 5.0f, 0, 3.0f);
    if (bHit)
    {
        DrawDebugSphere(World, HitResult.Location, 25.0f, 12, FColor::Red, false, 5.0f);
    }
}
코드 설명
  • FVector StartLocation, FVector EndLocation: 트레이스의 시작점과 끝점을 정의합니다. 이 코드는 GetActorEyesViewPoint가 제공하는 Pawn의 눈 위치·시야를 사용합니다. 3인칭 FollowCamera 위치와 같다고 가정하지 않으며, 카메라 기준이 필요하면 실제 카메라 컴포넌트를 연결해야 합니다.
  • FCollisionQueryParams TraceParams: 트레이스에 대한 추가 설정을 정의합니다.
    • AddIgnoredActor(this): 트레이스 시 특정 액터(여기서는 자기 자신)를 무시하여, 자기 자신과 충돌하는 것을 방지합니다.
    • bTraceComplex: 복잡 충돌을 사용할지 요청합니다. 단순·복잡 형상 선택은 에셋의 Collision Complexity 설정에도 영향을 받으며 비용과 적합성은 대상 형상에 따라 확인합니다.
  • FHitResult HitResult: 트레이스 결과가 저장되는 구조체입니다. 충돌이 발생하면 히트한 액터, 컴포넌트, 충돌 위치, 충돌 노멀(법선) 벡터 등 다양한 정보가 채워집니다.
  • World->LineTraceSingleByChannel(...): 실제 라인 트레이스를 실행하는 함수입니다.
    • ECollisionChannel::ECC_Visibility: Project Settings > Collision의 Trace Channels에서 정의된 Visibility 채널에 대해서만 트레이스를 수행합니다. 이 Single 호출은 해당 채널에 대한 첫 Block 결과를 반환합니다. Overlap 결과 배열이 필요한 경우 Multi 계약을 사용합니다.
  • DrawDebugLine / DrawDebugSphere: 개발 및 디버깅 목적으로 뷰포트에 트레이스 선과 히트 지점을 시각적으로 표시해줍니다. 게임 출시 시에는 제거하거나 디버그 빌드에서만 활성화해야 합니다.

예시: 쿼리 순서와 반환값을 함께 읽기

원 예제처럼 Single By Channel을 쓰되 계산을 위해 선의 시작 X=0 cm, 단위 방향 +X, 길이 1000 cm라고 가정하면 끝점은 X=1000 cm입니다. 선 위에 Overlap 응답 A가 100 cm, Block 응답 벽이 300 cm, Block 응답 B가 700 cm에 있습니다. 다른 필터·초기 겹침 문제가 없다면 Single의 결과는 첫 Block인 벽이며, A가 먼저 있었거나 B도 선 위에 있다는 이유로 B를 선택하지 않습니다. 길이는 1000 cm=10 m이고, 원 TraceDistance 기본값 10000 cm=100 m와 구별합니다.

실습에서는 헤더의 FireWeapon 선언과 .cpp 정의를 실제 캐릭터 클래스에 연결하고, 플레이어 입력 이벤트에서 한 번 호출하도록 준비합니다. 예제는 입력 매핑이나 카메라 컴포넌트를 생성하는 완성 프로젝트가 아닙니다. 같은 위치·방향으로 놓인 쿼리 참여 대상에 Visibility 응답을 Block으로 맞추고 로그와 디버그 선을 비교한 뒤, 응답 하나만 바꾸어 차이를 확인합니다. 원 Damage 호출은 주석이므로 Trace Hit 로그만 보고 실제 데미지가 적용됐다고 판정하지 않습니다.

Overlap 배열과 bool 판단하기

위 배치를 유지하고 Channel Multi 계약을 선택했다고 가정합니다. 처음 응답에서 배열에 포함될 대상과 bool을 예상하세요. 이어서 벽과 B만 Ignore로 바꾸고 A의 Overlap을 남기면 배열과 bool은 어떻게 달라질까요? bool=false라는 이유만으로 결과 배열이 비었다고 처리해도 되는지도 설명하세요.

채널 Multi 계약에 따라 풀이하기

처음에는 벽 앞의 A와 첫 Block인 벽을 반환하고 bool은 true입니다. 벽 뒤의 B까지 관통해 모두 반환하는 계약이 아닙니다. 두 Block을 Ignore로 바꾸면 A의 Overlap 결과는 남을 수 있지만 Blocking Hit가 없으므로 bool은 false입니다. 이 문제는 Channel Multi 계약의 독립 연습이며, 원 FireWeapon 코드가 Single 대신 Multi를 실제 실행한 결과가 아닙니다. 채널 응답과 객체 타입 필터도 서로 다른 선택입니다.

충돌 채널과 트레이스

라인 트레이스는 충돌 채널 시스템과 밀접하게 연관되어 있습니다.

Project Settings > Collision에는 Object Channels와 Trace Channels가 있습니다.

  • Object Channels: 액터/컴포넌트 자체가 어떤 타입의 오브젝트인지 정의합니다. (예: Pawn, WorldStatic, PhysicsBody)
  • Trace Channels: 라인 트레이스가 어떤 종류의 가상 선인지를 정의합니다. (예: Visibility, Camera)

트레이스를 수행할 때, 트레이스 함수에 지정된 Trace Channel과, 월드 내 각 오브젝트의 Object Channel 또는 Collision Profile 간의 상호작용 규칙에 따라 충돌 여부가 결정됩니다.

채널의 응답과 Single/Multi 함수의 반환 계약을 함께 해석해야 합니다.


트레이스 쿼리 타입 (Trace Query Types)

트레이스 함수를 호출하기 전에, 트레이스가 어떤 종류의 오브젝트를 감지할 것인지 설정하는 것이 중요합니다.

  • LineTrace…ByChannel은 대상의 지정 채널에 대한 응답을 검사합니다. Visibility, Camera 또는 커스텀 트레이스 채널을 목적에 맞게 고릅니다.
  • WorldStatic, WorldDynamic, Pawn 같은 오브젝트 타입만 찾으려면 FCollisionObjectQueryParams에 타입을 넣고 LineTrace…ByObjectType을 사용합니다. 같은 enum 값을 ByChannel 인자에 넣는 것만으로 타입 필터가 되지는 않습니다.

라인 트레이스 시스템은 언리얼 엔진에서 정교하고 효율적인 월드 쿼리 기능을 제공합니다.

직접적인 물리적 접촉 없이도 원하는 정보를 얻을 수 있으므로, 총알 히트 감지, AI 시야, 상호작용 등 다양한 게임플레이 메커니즘을 구현하는 데 필수적인 도구입니다.

트레이스의 유형(Line, Sphere, Box, Capsule), 채널/오브젝트 타입별 감지, 그리고 결과(FHitResult) 처리 방법을 숙지하면 강력한 게임플레이 시스템을 구축할 수 있을 것입니다.