파티클, 사운드 효과
아이템 획득 시, 파티클과 함께 소리가 재생되도록 구현
수많은 작은 입자(파티클)를 빠르게 생성하고 움직이며, 각 파티클의 위치, 크기, 색깔, 수명 등을 조절해주는 시스템
파티클 효과의 설계도 역할을 하는 Asset
게임 내에서 실질적으로 파티클을 재생하거나 제어하는 컴포넌트
월드에 배치되어 ParticleSystem(템플릿)을 참조해 파티클을 실제로 보여주는 역할
파티클을 켜거나 끄거나 위치를 조절하는 행동도 여기서 수행
언리얼 엔진의 모든 사운드 관련 기본 클래스
SoundWave, SoundCue 둘 다 이 클래스를 상속받아 사용
BaseItem클래스에 파티클, 사운드를 넣어줌// BaseItem.h
UCLASS()
class SPARTPROJECT_API ABaseItem : public AActor, public IItemInterface
{
// ... //
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Item|Effects")
UParticleSystem* PickupParticle;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Item|Effects")
USoundBase* PickupSound;
};
// BaseItem.cpp
void ABaseItem::ActivateItem(AActor* Activator)
{
UParticleSystemComponent* Particle = nullptr;
if (PickupParticle) {
Particle = UGameplayStatics::SpawnEmitterAtLocation(
GetWorld(), // 파티클 생성할 월드
PickupParticle,
GetActorLocation(),
GetActorRotation(),
false // 파티클 효과 종료 후 자동으로 메모리에서 제거 할지 말지
);
}
// Particle 직접 제거
if (Particle) {
FTimerHandle DestroyParticleTimerHandle;
GetWorldTimerManager().SetTimer(
DestroyParticleTimerHandle,
[Particle]() { Particle->DestroyComponent(); },
1.0f,
false
);
}
// 사운드 출력
UAudioComponent* Audio = nullptr;
if (PickupSound) {
Audio = UGameplayStatics::SpawnSoundAtLocation(
GetWorld(),
PickupSound,
GetActorLocation()
);
}
// 사운드 직접 제거
if (Audio) {
FTimerHandle DestroyAudioTimerHandle;
GetWorldTimerManager().SetTimer(
DestroyAudioTimerHandle,
[Audio]()
{
Audio->Stop();
Audio->DestroyComponent();
},
1.0f,
false
);
}
}
SpawnEmitterAtLocation : 파티클 생성 함수
GetWorld 매개인자 : 파티클 생성할 월드false 매개인자 : 파티클 효과 종료 후 자동으로 메모리에서 제거 할지 말지타이머 핸들러 이용하여 Particle과 Sound를 1초후에 제거
람다함수 통해, 1초 후에 실행될 일회성 콜백 함수를 간결하게 작성, 실행
Sound는 Stop 먼저 해주고 제거해야, 소리도 제거됨
지뢰의 경우, 접촉 시뿐만 아니라 폭발시에도 파티클/사운드 존재
따라서, 지뢰에만 추가적으로 폭발 시 사용할 파티클과 사운드 및 동일한 로직 추가

레벨 시간이 1초 이내로 남았을 때, 아이템을 획득하면 액세스 위반 에러가 발생
이유로는, 레벨이 전환되면서 기존에 생성된 모든 인스턴스는 제거되었는데, 파티클과 사운드를 제거하기 위한 핸들러는 남아있었음
따라서 타이머 1초가 지나고, 이미 사라진 파티클과 사운드에 접근하려해서 에러 발생
파티클과 사운드 포인터를 TWeakObjectPtr<UParticleSystemComponent>와 TWeakObjectPtr<UAudioComponent>로 선언
IsValid를 이용해 안전하게 체크
TWeakObjectPtr<UParticleSystemComponent> Particle;
// Particle 생성 로직
if (Particle.IsValid())
{
FTimerHandle DestroyParticleTimerHandle;
GetWorldTimerManager().SetTimer(
DestroyParticleTimerHandle,
[Particle]()
{
if(Particle.IsValid()) // Particle 존재할 때만
Particle->DestroyComponent();
},
1.0f,
false
);
}
TWeakObjectPtr<UAudioComponent> Audio;
// 사운드 생성 로직
if (Audio.IsValid())
{
FTimerHandle DestroyAudioTimerHandle;
GetWorldTimerManager().SetTimer(
DestroyAudioTimerHandle,
[Audio]()
{
if (Audio.IsValid())
{
Audio->Stop();
Audio->DestroyComponent();
}
},
1.0f,
false
);
}