TIL_041: 아이템 객체 생성(2), 타이머, 범위 감지

김펭귄·2025년 10월 1일

Today What I Learned (TIL)

목록 보기
41/115

오늘 학습 키워드

  • 아이템 객체에 컴포넌트 생성

  • Collision Preset (Custom)

  • 타이머

  • 범위 감지

1. 컴포넌트 생성

  • overlap이나 hit 이벤트를 발동시키기 위해 collision sphere/box를 추가해줌

  • static mesh에서 할 수도 있지만, 그러면 static mesh에서 하는 계산이 무거워지기 때문에, 따로 collision component를 추가해주는 것이 좋음

// BaseItem.h
#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "ItemInterface.h"
#include "BaseItem.generated.h"

class USphereComponent;

UCLASS()
class SPARTPROJECT_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;

	// ... //
};

// 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 Preset을 OverlapAllDynamic으로 설정
    Collision->SetCollisionProfileName(TEXT("OverlapAllDynamic"));
	Collision->SetupAttachment(Scene);

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

VisibleAnyWhere

  • 에디터에서 변수 값을 보기만 가능하게 하며, 객체 수정을 막음

  • 예를 들어, UStaticMeshComponent* 같은 포인터 변수를 VisibleOnly로 설정 시, 변수(포인터)가 다른 객체를 가리키도록 바꾸는 행위(재할당)를 막음

ptr = &b;	// 여기서 ptr의 가리키는 대상이 바뀌지 못하게 함
  • 그러나 객체 내부의 여러 속성은 수정 가능 (Mesh 에셋 등)

  • VisibleAnywhere여도 블루프린트 에디터(디테일 패널)에서 내부 속성을 수정하여 StaticMesh를 설정해줄 수 있다

  • 즉, 객체 참조는 고정되어 있지만, 해당 객체의 멤버 데이터나 에셋은 바꿀 수 있다

2. Collision Preset (Custom)

  • Query Only : 충돌이벤트(Overlap, Hit)는 감지하고 물리적 반응(밀림, 튕김)은 없음
  • Physics Only : 물리적 반응만 있고 충돌이벤트(Hit/Overlap)는 없음
  • Collision Enabled : 둘 다 존재

3. Overlap Binding

  • 언리얼 블루프린트의 Event Graph에서 Collision 컴포넌트의 BeginOverlap 노드의 경우 사진과 같이 6개의 값을 반환함

  • 따라서 우리가 만들었던 InterfaceItem의 OnItemBeginOverlap의 매개인자를 위와같이 바꾸어줘야함

// ItemInterface.h
UFUNCTION()
virtual void OnItemBeginOverlap(
	UPrimitiveComponent* OverlappedComp,
	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;
  • OverlappedComp : overlap 발생한 자기 자신

  • OtherActor : overlap 시킨 상대방

  • OtherComp ': 충돌일으킨 상대방의 컴포넌트

  • OtherBodyIndex, bFrmoSweep, SweepResult : 물리효과 관련으로 나중에 학습

  • EndOverlap같은 경우는 뒤의 2개인자는 필요 없음

  • 생성자에서 동적으로 Binding해주어, overlap시 만들어준 함수가 연결되게 해줌

  • 런타임중에 binding해주는 것이므로, OnItemBeginOverlapOnItemEndOverlap은 InterfaceItem헤더에서 UFUNCTION으로 리플렉션 시스템에 등록해줌

4. BeginOverlap

  • 이제 연동되었으므로, OnItemBeginOverlap함수를 구현해줌
void ABaseItem::OnItemBeginOverlap(
	UPrimitiveComponent* OverlappedComp,
	AActor* OtherActor,
	UPrimitiveComponent* OtherComp,
	int32 OtherBodyIndex,
	bool bFromSweep,
	const FHitResult& SweepResult)
{
	// OtherActor가 null아닌지 확인 && Actor의 Tag가 player인지 확인
	if (OtherActor && OtherActor->ActorHasTag("Player"))	
	{
		GEngine->AddOnScreenDebugMessage(-1, 2.0f, FColor::Green, 
        					FString::Printf(TEXT("Overlap!!!")));
		ActivateItem(OtherActor);
	}
}

void ABaseItem::ActivateItem(AActor* Activator) 
{
	GEngine->AddOnScreenDebugMessage(-1, 2.0f, FColor::Green, 
        					FString::Printf(TEXT("Activate!!!")));
	Destroy();
}
  • GEngine->AddOnScreenDebugMessage() : 스크린에 출력해주는 함수
    -1은 매번 새로운 아이디를 생성, 2초동안 출력, 초록색으로, Overlap!!!을 출력
  • OtherActor->ActorHasTag("Player") : OtherActor가 "Player"라는 Tag가지는지 확인

  • 캐릭터 블루프린트에서 "Player"라고 Tag를 달아줄 수 있다

시연 영상

5. Mine 폭발 영역 설정

  • 지뢰의 경우, Overlap을 감지할 컴포넌트(Collision)와 추가로 폭발하는 범위에 플레이어가 있는지 확인할 또다른 Collision 컴포넌트가 필요

  • BaseItem에서 SphereComponent를 이용해 collision을 만든것과 동일하게 하면 된다

AMineItem::AMineItem()
{
	ExplosionDelay = 5.0f;
	ExplosionRadius = 300.0f;
	ExplosionDamage = 30;
	ItemType = "Mine";

	ExplosionCollision = CreateDefaultSubobject<USphereComponent>(TEXT("ExplosionCollision"));
	ExplosionCollision->InitSphereRadius(ExplosionRadius);
	ExplosionCollision->SetCollisionProfileName(TEXT("OverlapAllDynamic"));
	ExplosionCollision->SetupAttachment(Scene);
}
  • 그 다음으로, 5초 뒤에 터지게 할 타이머 설정과 ExplosionCollision 내에 있을 시 피해를 입도록 구현해야 한다

타이머 설정

  • 타이머 핸들러 : 시간을 계산해주는 시계

  • 월드에 존재하는 여러 개의 타이머 핸들러를 타이머 매니저가 관리해줌

  • 지뢰가 Activate되었을 때부터 시간을 재도록 구현

// MineItem.h
UCLASS()
class SPARTPROJECT_API AMineItem : public ABaseItem
{
	// ... //
    
    FTimerHandle ExplosionTimerHandle;	// 타이머 핸들러

    virtual void ActivateItem(AActor* Activator) override;
    virtual void Explode();
};

// MineItem.cpp
void AMineItem::ActivateItem(AActor* Activator)
{
	GetWorld()->GetTimerManager().SetTimer(
		ExplosionTimerHandle,
		this,
		&AMineItem::Explode,
		ExplosionDelay,
        false
	);
}
  • GetWorld()->GetTimerManager().SetTimer() : 타이머 생성 및 실행
    • ExplosionTimerHandle : 헤더에서 선언한 타이머핸들러 객체
    • this : 시간 되었을 시 호출할 함수의 객체
    • &AMineItem::Explode : 시간 되었을 시 호출할 함수
    • ExplosionDelay : 타이머 시간
    • false : 타이머 반복 여부

Explode

  • 타이머가 종료 후 호출되어 폭발 로직을 실행

  • ExplosionCollision에 플레이어가 있을 시 피해를 입음

void AMineItem::Explode()
{
	TArray<AActor*> OverlappingActors;
	ExplosionCollision->GetOverlappingActors(OverlappingActors);

	for (AActor* Actor : OverlappingActors) {
		if (Actor && Actor->ActorHasTag("Player")) {
			GEngine->AddOnScreenDebugMessage(
            	-1, 
                2.0f, 
                FColor::Red, 
                FString::Printf(TEXT("Player damaged : %d"), ExplosionDamage)
                );
		}
	}

	DestroyItem();
}
  • ExplosionCollision->GetOverlappingActors(arr) : 현재 Overlap되어 있는 모든 액터들을 arr에 추가해줌

  • 오버래핑 된 액터중에 플레이어 캐릭터가 있을 경우 피해를 입힘

시연 영상

profile
반갑습니다

0개의 댓글