[내일배움캠프/UE] 아이템 상호작용 활성화

김세희·2025년 7월 2일

✍️Today I Learned

  1. Collision
  2. 이벤트 바인딩

Collision

  1. Overlap
    객체를 통과하거나 겹쳐짐
  2. Hit
    객체에 막힘

두 이벤트는 서로 다른 충돌 처리 방식이라 동시에 작동하지 않는다.

Collision Presets

어떤 충돌을 감지하거나 무시할지 설정

  1. NoCollision
    충돌 감지를 하지 않는다.
    ex) 하늘에 있는 오브젝트, 장식, 실질적으로 상호작용하지 않는 오브젝트
  2. BlockAll
    모든 객체를 막는다.
    ex) 벽, 바닥
  3. OverlapAll
    감지 센서
    ex) 트리거 존
  4. BlockAllDynamic
    움직이는 객체만 막는다. 벽이나 지형 무시
    ex) 문
  5. OverlapAllDynamic
    움직이는 객체랑만 오버랩 이벤트를 발생시킨다.
    ex) 감지 센서
  6. Pawn
    플레이어나 AI같은 폰 타입 객체의 충돌을 막는다.

Collision Enabled

  1. Collision Enabled (Query and Physics)
    충돌도 감지하고 물리적 반응도 활성화
  2. Query Only
    충돌은 감지하지만 물리적 반응은 비활성화
  3. Physics Only
    물리적 반응은 하지만 충돌 감지 이벤트 비활성화

플레이어 캐릭터에 태그 추가
해당 블루프린트 Details -> Actor -> Advanced -> Tags 추가
오버랩 이벤트 발생 시 플레이어인지 확인하기 위해 추가한다.


이벤트 바인딩

아이템 인터페이스를 구현하는 BaseItem 클래스에서 오버랩 이벤트에 클래스의 오버랩 함수를 바인딩한다.

이벤트 바인딩하는 이유

이벤트 바인딩은 런타임에서 이루어지기 때문에 게임 실행 전에는 어떤 객체가 어떤 상황에서 이벤트를 발생시킬 지 알 수 없다. 이런 예측 불가능한 상황에 대비하려면 이벤트 함수를 게임 실행 중에 동적으로 연결해야한다.

// BaseItem.cpp
#include "BaseItem.h"
#include "Components/SphereComponent.h"

// Sets default values
ABaseItem::ABaseItem()
{
	PrimaryActorTick.bCanEverTick = false;

	Scene = CreateDefaultSubobject<USceneComponent>(TEXT("Scene"));
	SetRootComponent(Scene);

	Collision = CreateDefaultSubobject<USphereComponent>(TEXT("Collision"));
	// 콜리전 프리셋 설정
	Collision->SetCollisionProfileName(TEXT("OverlapAllDynamic"));
	Collision->SetupAttachment(Scene);

	StaticMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("StaticMesh"));
	StaticMesh->SetupAttachment(Collision);

	// 이벤트 바인딩
	Collision->OnComponentBeginOverlap.AddDynamic(this, &ABaseItem::OnItemOverlap);
	Collision->OnComponentEndOverlap.AddDynamic(this, &ABaseItem::OnItemEndOverlap);
}

델리게이트 시그니처

콜리전 메시에서 AddDynamic으로 OnComponentBeginOverlapOnComponentEndOverlap 델리게이트를 특정 함수와 바인딩한다. 델리게이트는 함수 시그니처가 정확히 일치해야 바인딩할 수 있으므로 매개변수 타입을 맞춰주어야 한다.
또한 AddDynamic 으로 바인딩할 경우 해당 함수를 리플렉션 시스템에 등록해야 엔진이 런타임 때 찾을 수 있으므로 UFUNCTION()매크로는 필수이다.
인터페이스에서 리플렉션에 등록하면 이후 구현하는 클래스에서는 할 필요 없다.

// ItemInterface.h

// 플레이어가 진입했을 때
UFUNCTION()
virtual void OnItemOverlap(
	UPrimitiveComponent* OverlappedComp,	// 오버랩 발생한 자기 자신 ex) 콜리전 메시
	AActor* OtherActor,	// 부딪힌 액터
	UPrimitiveComponent* OtherComp,	// 부딪힌 액터에 붙어있는 충돌을 일으킨 컴포넌트
	int32 OtherBodyIndex,
	bool bFromSweep,
	const FHitResult& SweepResult) = 0;
// 플레이어가 이탈했을 때
UFUNCTION()
virtual void OnItemEndOverlap(
	UPrimitiveComponent* OverlappedComp,
	AActor* OtherActor,
	UPrimitiveComponent* OtherComp,
	int32 OtherBodyIndex) = 0;

출처: 스파르타코딩 내일배움캠프

0개의 댓글