📍 4주차 4강
P_ 또는 Niagara_접두어를 사용하여 구분둘 다 SoundBase의 상속을 받음
나머지 아이템들은 BaseItem의 상속을 받았기 때문에 BaseItem에만 해도 됨
// BaseItem.h
UParticleSystem* PickupParticle; // 파티클 시스템 추가
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Item|Effects")
USoundBase* PickupSound; // 사운드 추가
// BaseItem.cpp
#include "Kismet/GameplayStatics.h" // 파티클, 사운드
void ABaseItem::ActivateItem(AActor* Activator)
{
// 지정된 위치랑 회전에서 파티클 재생해 ~
if (PickupParticle)
{
// 지정된 위치나 회전에 따라 파티클 효과 생성하는 함수
UGameplayStatics::SpawnEmitterAtLocation(
GetWorld(), // 현재 게임이 실행되고 있는 월드 객체 가져옴<-파티클 생성한 월드 정보 필요
PickupParticle, // 지정해놓은 파티클 에셋
GetActorLocation(), // 이 아이템의 월드 위치 가져옴
GetActorRotation(), // 이 아이템의 회전 위치 가져옴
true // AutoDistroy : 파티클 효과 끝난 이후에 메모리에서 자동 제거 되도록 설정
);
}
// 지정된 위치에서 사운드 효과 재생해 ~
if (PickupSound)
{
UGameplayStatics::PlaySoundAtLocation(
GetWorld(),
PickupSound,
GetActorLocation()
);
}
}




지금은 그냥 override만 해놓고 부모 거 안 부름!
// MineItem.cpp
void AMineItem::ActivateItem(AActor* Activator) // 활성화되고 5초 후에 폭발
{
Super::ActivateItem(Activator); // → 다른 아이템들에도 추가하기
// ...
}
파티클은 아이템에 붙어 있는 게 아니라 자체적인 라이프 사이클이니까
따로 삭제 해줘야 함 → false로
// MineItem.h
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Item|Effects")
UParticleSystem* ExplosionParticle; // 파티클 시스템 추가
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Item|Effects")
USoundBase* ExplosionSound; // 사운드 추가
// MineItem.cpp
#include "MineItem.h"
#include "Components/SphereComponent.h"
#include "Kismet/GameplayStatics.h"
#include "SpartaCharacter.h"
#include "Particles/ParticleSystemComponent.h"
AMineItem::AMineItem()
{
ExplosionDelay = 5.0f; // 기본 폭발 지연 시간 설정
ExplosionRadius = 300.0f; // 기본 폭발 범위 설정
ExplosionDamage = 30.0f; // 기본 폭발 피해 설정
ItemType = "Mine"; // 아이템 타입 설정
bHasExploded = false;// 오버랩 연속 안되게
// 콜리전 컴포넌트 추가 (반경)
ExplosionCollision = CreateDefaultSubobject<USphereComponent>(TEXT("ExplosionCollision"));
ExplosionCollision->InitSphereRadius(ExplosionRadius); // 300.0f 넣기
ExplosionCollision->SetCollisionProfileName(TEXT("OverlapAllDynamic")); // 모든 동적 오버랩 허용
ExplosionCollision->SetupAttachment(Scene); // 루트 컴포넌트인 씬 컴포넌트에 부착
}
void AMineItem::ActivateItem(AActor* Activator) // 활성화되고 5초 후에 폭발
{
if (bHasExploded) return;
Super::ActivateItem(Activator);
// 게임 월드에는 각자의 타이머를 관리하는 타이머 매니저가 있음
// 타이머 핸들러 : 각자의 타이머를 갖고 있음
// 월드에서 타이머 매니저 부름
GetWorld()->GetTimerManager().SetTimer(
ExplosionTimerHandle, // 타이머 달아줌
this, // 타이머가 끝나면 호출할 대상 : 이 객체에
&AMineItem::Explode, // 호출할 함수
ExplosionDelay, // 지연 시간
false // 반복 여부 (false면 한 번만 실행)
);
bHasExploded = true;
}
void AMineItem::Explode()
{
// 이미 선언된 'Particle' 변수를 재사용
UParticleSystemComponent* Particle = nullptr; // 다시 초기화
if (ExplosionParticle)
{
// 이미 선언된 변수 'Particle'을 재사용
Particle = UGameplayStatics::SpawnEmitterAtLocation(
GetWorld(),
ExplosionParticle,
GetActorLocation(), // GetActorLocation() 함수 호출
GetActorRotation(), // GetActorRotation() 함수 호출
false
);
}
if (ExplosionSound)
{
UGameplayStatics::PlaySoundAtLocation(
GetWorld(),
ExplosionSound,
GetActorLocation()
);
}
TArray<AActor*> OverlappingActors; // 범위 내 겹치는 액터 검색
ExplosionCollision->GetOverlappingActors(OverlappingActors);
// 범위 내 돌면서 태그 확인
for (AActor* Actor : OverlappingActors)
{
if (Cast<ASpartaCharacter>(Actor))
{
UGameplayStatics::ApplyDamage(
Actor, // 데미지를 받을 액터
ExplosionDamage, // 데미지의 양
nullptr, // 데미지를 유발한 주체
this, // 데미지를 입힌 액터
UDamageType::StaticClass() // 데미지의 유형
);
}
}
DestroyItem();
if (Particle)
{
FTimerHandle DestroyParticleTimerHandle;
// 람다 함수 - 이름이 없다?
// 직접 구현하긴 뭐하고 간단하게 함수같이 쓰고 싶을 때 람다 쓰기
GetWorld()->GetTimerManager().SetTimer(
DestroyParticleTimerHandle,
[Particle]()
{
Particle->DestroyComponent();
},
2.0f,
false
);
}
}
BaseItem도 적용해주기
근데 이건 너무 길어서 그냥 나중에 코드 보기...