I am going through the variable, timers, and events tutorial and have one question about deactivating the included P_Explosion asset. I have decided to try to load the asset with c++ instead of using a blueprint as shown in the tutorial.
As of now I have it working by using ParticleSystemComp->Deactivate()
and ParticleSystemComp->Activate()
in an attempt to hide the explosion until the countdown finishes.
And I am initializing ParticleSystemComp
in the ACountdown()
constructor at program start.
However, when this gets initialized, the explosion plays, even though I am attempting to call Deactivate()
immediately after creating the object. It then plays again at the desired time when calling Activate()
in CountdownHasFinished()
.
After seeing the suggestion in Rider, I looked more into DeactivateImmediate to see if that would hide/prevent the Particle System from showing at program start.
Unfortunately, when I use DeactivateImmediate()
in place of Deactivate()
I get a runtime error and Unreal crashes/closes:
Countdown.cpp:
#include "Countdown.h"
#include "UnrealExp1.h"
#include "Components/TextRenderComponent.h"
#include "Particles/ParticleSystem.h"
#include "Particles/ParticleSystemComponent.h"
ACountdown::ACountdown()
{
// Set this actor to call Tick() every frame.
PrimaryActorTick.bCanEverTick = false;
CountdownText = CreateDefaultSubobject<UTextRenderComponent>(TEXT("CountdownNumber"));
CountdownText->SetHorizontalAlignment(EHTA_Center);
CountdownText->SetWorldSize(150.0f);
RootComponent = CountdownText;
CountdownTime = 3;
const wchar_t* ParticlePath = TEXT("ParticleSystem'/Game/StarterContent/Particles/P_Explosion.P_Explosion'");
static ConstructorHelpers::FObjectFinder<UParticleSystem> ParticleSystemAsset(ParticlePath);
ParticleSystemComp = CreateDefaultSubobject<UParticleSystemComponent>(TEXT("Particles"));
ParticleSystemComp->SetTemplate(ParticleSystemAsset.Object);
ParticleSystemComp->DeactivateImmediate();
}
// Called when the game starts or when spawned
void ACountdown::BeginPlay()
{
Super::BeginPlay();
UpdateTimerDisplay();
GetWorldTimerManager().SetTimer(CountdownTimerHandle, this, &ACountdown::AdvanceTimer, 1.0f, true);
}
// Called every frame
void ACountdown::Tick( float DeltaTime )
{
Super::Tick(DeltaTime);
}
void ACountdown::UpdateTimerDisplay() const
{
const int MaxTime = FMath::Max(CountdownTime, 0);
CountdownText->SetText(FText::AsNumber(MaxTime));
}
void ACountdown::CountdownHasFinished() const
{
ParticleSystemComp->Activate();
CountdownText->SetText(FText::FromString("BLAM!"));
}
void ACountdown::AdvanceTimer()
{
--CountdownTime;
UE_LOG(LogTemp, Warning, TEXT("CountdownTime: %d"), CountdownTime);
UpdateTimerDisplay();
if (CountdownTime < 1)
{
GetWorldTimerManager().ClearTimer(CountdownTimerHandle);
CountdownHasFinished();
}
}
I also tried to declare the FObjectFinder
in the header and make it into a class field/member so that I could just call it when needed, but that also did not work.
How can I get the particle system to play just once in CoundownHasFinished()
and prevent it from playing in when the program starts?
Any suggestions are greatly appreciated… thanks!