Hi,
I’m following the Variables, Timers & Events tutorial
I’ve gone through pages 1-3 and everything works great, except that calling CountdownHasFinished() isn’t resulting in CountdownHasFinished_Implementation() being called.
This results in the text being displayed reaching 0, and remaining on 0 forever, instead of being changed to “Go!”
I’ve looked over numerous related forum posts and answers, but can’t see any similar issues with the answers I need (apologies if I’ve missed one).
header:
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "Components/TextRenderComponent.h"
#include "Engine/EngineTypes.h"
#include "Countdown.generated.h"
UCLASS()
class EVENTSLEARNING_API ACountdown : public AActor
{
GENERATED_BODY()
public:
// Sets default values for this actor's properties
ACountdown();
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
public:
// Called every frame
virtual void Tick(float DeltaTime) override;
// How long, in seconds, the timer countdown will run for
UPROPERTY(EditAnywhere)
int32 CountdownTimeStartingValue;
int32 CountdownTime;
UTextRenderComponent* CountdownText;
// Replaces text in world with text displaying correct time
void UpdateTimerDisplay();
// Ticks the timer down every second
void AdvanceTimer();
// Performed when countdown timer has finished
UFUNCTION(BlueprintNativeEvent)
void CountdownHasFinished();
virtual void CountdownHasFinished_Implementation();
FTimerHandle CountdownTimerHandle;
};
code:
// Fill out your copyright notice in the Description page of Project Settings.
#include "Countdown.h"
#include "Components/TextRenderComponent.h"
#include "Engine/EngineTypes.h"
#include "Engine/World.h"
// Sets default values
ACountdown::ACountdown()
{
// Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true;
CountdownText = CreateDefaultSubobject<UTextRenderComponent>(TEXT("CountdownNumber"));
CountdownText->SetHorizontalAlignment(EHTA_Center);
CountdownText->SetWorldSize(150.0f);
RootComponent = CountdownText;
CountdownTime = 3;
}
// Called when the game starts or when spawned
void ACountdown::BeginPlay()
{
Super::BeginPlay();
CountdownTime = CountdownTimeStartingValue;
UpdateTimerDisplay();
GetWorldTimerManager().SetTimer(CountdownTimerHandle, this, &ACountdown::AdvanceTimer, 1.0f, true);
}
// Called every frame
void ACountdown::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
}
void ACountdown::UpdateTimerDisplay()
{
CountdownText->SetText(FString::FromInt(FMath::Max(CountdownTime, 0)));
}
void ACountdown::AdvanceTimer()
{
--CountdownTime;
UpdateTimerDisplay();
if (CountdownTime < 1)
{
// Clean up the time handle and stop the timer
GetWorldTimerManager().ClearTimer(CountdownTimerHandle);
CountdownHasFinished();
GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Yellow, TEXT("Function called"));
}
}
void ACountdown::CountdownHasFinished_Implementation()
{
// Change to a special readout
CountdownText->SetText(TEXT("GO!"));
GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Yellow, TEXT("Implementation Function called"));
}
Many thanks