언리얼에서 아이템을 플레이어가 가까이 가면 자동으로 획득 하는 기능을 아이템 구현할 때 사용하며,
별도의 함수 호출 없이 자동으로 처리되어서 간편하게 구현해서 사용이 가능함
충돌컴포넌트(Sphere, Box Component 등)로 아이템 주변에 영역을 생성
플레이어가 영역 안에 들어오면 Overlap 이벤트가 발생 및 이를 감지하여 아이템 획득 로직 실행 가능
Overlap - 겹치면 실행(아이템 획득 및 트리거 존 감지 등)
Hit - 부딪히는 물리 충돌이 일어나면 실행(총알, 벽 등)
// BaseItem.h
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "ItemInterface.h"
#include "BaseItem.generated.h"
class USphereComponent;
UCLASS()
class SPARTA_API ABaseItem : public AActor, public IItemInterface
{
GENERATED_BODY()
public:
ABaseItem();
protected:
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Item")
FName ItemType;
// 루트 컴포넌트
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Item|Component")
USceneComponent* Scene;
// 충돌 컴포넌트
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Item|Component")
USphereComponent* Collision;
// 스태틱 메시
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Item|Component")
UStaticMeshComponent* StaticMesh;
virtual void OnItemOverlap(
// 내 충돌 컴포넌트 (아이템의 Collision, Sphere 등)
UPrimitiveComponent* OverlappedComp,
// 들어온 대상 (플레이어 등 액터)
AActor* OtherActor,
// 상대방의 충돌 컴포넌트 (플레이어 Capsule 등)
UPrimitiveComponent* OtherComp,
// 충돌된 바디 인덱스
int32 OtherBodyIndex,
// 어떻게 들어왔는지
bool bFromSweep,
// 충돌 상세 정보(위치, 방향 등)
const FHitResult& SweepResult) override;
virtual void OnItemEndOverlap(
UPrimitiveComponent* OverlappedComp,
AActor* OtherActor,
UPrimitiveComponent* OtherComp,
int32 OtherBodyIndex) override;
virtual void ActivateItem(AActor* Activator) override;
virtual FName GetItemType() const override;
void DestroyItem();
};
// BaseItem.cpp
#include "BaseItem.h"
#include "Components/SphereComponent.h"
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);
// Overlap 이벤트 연결(들어오면 실행)
Collision->OnComponentBeginOverlap.AddDynamic(this, &ABaseItem::OnItemOverlap);
// Overlap 이벤트 연결(나가면 실행)
Collision->OnComponentEndOverlap.AddDynamic(this, &ABaseItem::OnItemEndOverlap);
}
void ABaseItem::OnItemOverlap(
UPrimitiveComponent* OverlappedComp,
AActor* OtherActor,
UPrimitiveComponent* OtherComp,
int32 OtherBodyIndex,
bool bFromSweep,
const FHitResult& SweepResult)
{
// 플레이어인지 확인
if (OtherActor && OtherActor->ActorHasTag("Player"))
{ // 플레이어가 맞으면 화면에 메시지 출력
GEngine->AddOnScreenDebugMessage(-1, 2.0f, FColor::Green, FString::Printf(TEXT("Overlap!!!")));
// 아이템 획득 로직 호출
// Overlap 이벤트 발생시 ActivateItem 함수가 호출되며,
// 실제 아이템 획득 및 효과 기능, 효과 처리는 이 함수에서 실행됨
ActivateItem(OtherActor);
}
}
void ABaseItem::OnItemEndOverlap(
UPrimitiveComponent* OverlappedComp,
AActor* OtherActor,
UPrimitiveComponent* OtherComp,
int32 OtherBodyIndex)
{
}
// 아이템의 진짜 기능(여기서는 Overlap 됐는지 테스트용)
void ABaseItem::ActivateItem(AActor* Activator)
{
GEngine->AddOnScreenDebugMessage(-1, 2.0f, FColor::Green, FString::Printf(TEXT("Overlap!!")));
}
// 아이템 종류 반환
FName ABaseItem::GetItemType() const
{
return ItemType;
}
// 아이템 삭제
void ABaseItem::DestroyItem()
{
Destroy();
}
1. C++ 클래스로 생성한 아이템들(HealingItem, MineItem, SmallCoin, BigCoin)에 각 우클릭 >
Create Blueprint Class based on ~~~ 클릭 > BP_아이템이름 으로 지정 후 Blueprints 폴더에 생성
2. 각 BP 아이템 더블클릭 후 좌측 상단 Components 탭 > Static Mesh 클릭 >
우측 상단 Details 탭 > Static Mesh, Materials 원하는거로 설정
3. 좌측 상단 Components 탭 > SphereComponent 클릭 > Collision 클릭 > 우측 상단 Details 탭 >
검색창에 sphere 검색 후 Sphere Radius에서 조절 - 뷰포트에서 범위 확인 가능
4. BP_아이템 클래스들 더블클릭 > 우측 상단 Details 창 > Collision 탭 >
Collision Presets에 Overlap All Dynamic 등록
5. BP_Chracter 클래스 더블클릭 > 우측 상단 Details 창 > Actor 탭 >
Advanced > Tags 추가 후 Player 등록
누구랑 어떻게 충돌할지 정해놓는 설정
1. NoCollision
- 충돌 없음 이벤트도 없음
ex) 단순 배경 오브젝트(장식용 액터, 하늘 등)
2. BlockAll
- 모든 객체와 물리적으로 충돌하며 막음, Overlap Event는 발생하지 않음
ex) 벽, 바닥 등
3. OverlapAll
- 모든 객체와 겹쳐지며 Overlap Event 발생
ex) 트리거, 감지용 등
4. BlockAllDynamic
- 움직이는 객체의 충돌을 막고 고정된 객체와는 충돌하지 않음
ex) 플레이어랑만 충돌 등
5. OverlapAllDynamic
- 움직이는 객체와 겹쳐지며 Overlap Event 발생
ex) 아이템, 센서 등
6. Pawn
- 플레이어나 AI처럼 Pawn 타입 객체와만 충돌
ex) 플레이어, AI 등 캐릭터 전용
7. Custom
- 직접 설정
1. NoCollision
- 충돌 비활성
2. Query Only
- 이벤트만 감지, 물리 충돌은 없음(아이템용)
3. Physics Only
- 물리 충돌만 일어나며, 이벤트는 발생하지 않음
4. Query and Physics
- 충돌 및 이벤트 둘 다 활성화
설명 - 주석처리
// MineItem.h
#pragma once
#include "CoreMinimal.h"
#include "BaseItem.h"
#include "MineItem.generated.h"
UCLASS()
class SPARTA_API AMineItem : public ABaseItem
{
GENERATED_BODY()
public:
AMineItem();
protected:
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Item|Component")
USphereComponent* ExplosionCollision;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Mine")
float ExplosionDelay;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Mine")
float ExplosionRadius;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Mine")
int ExplosionDamage;
// 타이머 관리
// 지뢰가 발동되면 이 핸들을 이용해서 일정 시간 뒤에
// Explode() 함수가 실행되도록 설정
FTimerHandle ExplosionTimerHandle;
virtual void ActivateItem(AActor* Activator) override;
void Explode();
};
// MineItem.cpp
#include "MineItem.h"
#include "Components/SphereComponent.h"
AMineItem::AMineItem()
{
// 지뢰 초기값 설정
ExplosionDelay = 5.0f;
ExplosionRadius = 300.0f;
ExplosionDamage = 30.0f;
ItemType = "Mine";
// 폭발 범위 감지용 충돌 컴포넌트 생성
ExplosionCollision = CreateDefaultSubobject<USphereComponent>(TEXT("ExplosionCollision"));
// 폭발 범위 설정
ExplosionCollision->InitSphereRadius(ExplosionRadius);
// 폭발 범위 Overlap 상태 감지 설정
ExplosionCollision->SetCollisionProfileName(TEXT("OverlapAllDynamic"));
// 루트 컴포넌트에 부착
ExplosionCollision->SetupAttachment(Scene);
}
void AMineItem::ActivateItem(AActor* Activator)
{
// 플레이어가 지뢰 범위에 들어오면 실행되는 함수
// 타이머를 시작해서 일정 시간 뒤 Explode() 함수가 실행되도록 설정
GetWorld()->GetTimerManager().SetTimer(ExplosionTimerHandle, this, &AMineItem::Explode, ExplosionDelay);
}
void AMineItem::Explode()
{
// 폭발 범위에 누가 있는지 배열로 액터들을 가져옴
// 범위 내에 누가 있는지 검사
TArray<AActor*> OverlappingActors;
ExplosionCollision->GetOverlappingActors(OverlappingActors);
// 폭발 범위 내에 Player 태그가 붙어있는 액터만 골라냄
for (AActor* Actor : OverlappingActors)
{
if (Actor && Actor->ActorHasTag("Player"))
{
// 폭발 범위 내에 Player 태그가 붙어있는 액터가 있으면
// 화면에 데미지 메시지 출력
GEngine->AddOnScreenDebugMessage(-1, 2.0f, FColor::Red, FString::Printf(TEXT("Player damaged %d by MineItem"), ExplosionDamage));
}
}
DestroyItem();
}
설명 - 주석처리
// HealingItem.h
#pragma once
#include "CoreMinimal.h"
#include "BaseItem.h"
#include "HealingItem.generated.h"
UCLASS()
class SPARTA_API AHealingItem : public ABaseItem
{
GENERATED_BODY()
public:
AHealingItem();
protected:
// 회복량
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Healing")
int32 HealAmount;
virtual void ActivateItem(AActor* Activator) override;
};
// HealingItem.cpp
#include "HealingItem.h"
AHealingItem::AHealingItem()
{
HealAmount = 20.0f;
ItemType = "Healing";
}
void AHealingItem::ActivateItem(AActor* Activator)
{
if (Activator && Activator->ActorHasTag("Player"))
{
// 범위 내에 Player 태그가 붙어있는 액터가 있으면
// 화면에 체력회복 메시지 출력
GEngine->AddOnScreenDebugMessage(-1, 2.0f, FColor::Green, FString::Printf(TEXT("Player gained %d HP!"), HealAmount));
DestroyItem();
}
}
설명 - 주석처리
// CoinItem.h
#pragma once
#include "CoreMinimal.h"
#include "BaseItem.h"
#include "CoinItem.generated.h"
UCLASS()
class SPARTA_API ACoinItem : public ABaseItem
{
GENERATED_BODY()
public:
ACoinItem();
protected:
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Item")
int32 PointValue;
virtual void ActivateItem(AActor* Activator) override;
};
// CoinItem.cpp
#include "CoinItem.h"
ACoinItem::ACoinItem()
{
// 점수 기본값을 0으로 설정
PointValue = 0;
ItemType = "DefaultCoin";
}
void ACoinItem::ActivateItem(AActor* Activator)
{
if (Activator && Activator->ActorHasTag("Player"))
{
// 범위 내에 Player 태그가 붙어있는 액터가 있으면
// 화면에 점수 획득 메시지 출력
GEngine->AddOnScreenDebugMessage(-1, 2.0f, FColor::Green, FString::Printf(TEXT("Player gained %d points!"), PointValue));
DestroyItem();
}
}
설명 - 주석처리
// SmallCoinItem.h
#pragma once
#include "CoreMinimal.h"
#include "CoinItem.h"
#include "SmallCoinItem.generated.h"
UCLASS()
class SPARTA_API ASmallCoinItem : public ACoinItem
{
GENERATED_BODY()
public:
ASmallCoinItem();
virtual void ActivateItem(AActor* Activator) override;
};
// SmallCoinItem.cpp
#include "SmallCoinItem.h"
ASmallCoinItem::ASmallCoinItem()
{
PointValue = 10;
ItemType = "SmallCoin";
}
void ASmallCoinItem::ActivateItem(AActor* Activator)
{
// 부모의 기본 점수 획득 로직 사용
Super::ActivateItem(Activator);
// 스몰 코인만의 별도 동작은 여기에 추가
}
// BigCoinItem.h
#pragma once
#include "CoreMinimal.h"
#include "CoinItem.h"
#include "BigCoinItem.generated.h"
UCLASS()
class SPARTA_API ABigCoinItem : public ACoinItem
{
GENERATED_BODY()
public:
ABigCoinItem();
virtual void ActivateItem(AActor* Activator) override;
};
// BigCoinItem.cpp
#include "BigCoinItem.h"
ABigCoinItem::ABigCoinItem()
{
PointValue = 50;
ItemType = "BigCoin";
}
void ABigCoinItem::ActivateItem(AActor* Activator)
{
// 부모의 기본 점수 획득 로직 사용
Super::ActivateItem(Activator);
// 빅 코인만의 추가 동작(이펙트, 사운드 재생 등)을 여기서 추가
}
| 타이머 실행중에 레벨이 바뀌면 에디터가 종료되는 오류 (0) | 2026.04.21 |
|---|---|
| Unreal C++ 기초 8. 아이템 스폰 및 레벨 데이터 구현 (0) | 2026.04.17 |
| Unreal C++ 기초 6. InterFace 기반 아이템 클래스 생성 (0) | 2026.04.15 |
| Pawn 클래스 3D 캐릭터 만들기 (0) | 2026.04.14 |
| Unreal C++ 기초 5. GameMode와 Character 클래스를 활용해서 캐릭터 구현하기 (2) | 2026.04.09 |