So we have already discussed how to add a widget to the viewport, which means that it will be rendered on the player's screen.
However, what if we want to have UI elements that are toggled based on other factors, such as proximity to certain Actors, or a player holding a key down, or if we want a UI that disappears after a specified time?
GameMode
class called ToggleHUDGameMode
.BeginPlay
and EndPlay
.UPROPERTY
:UPROPERTY() FTimerHandle HUDToggleTimer;
TSharedPtr<SVerticalBox> widget;
BeginPlay
with the following code in the method body:void AToggleHUDGameMode::BeginPlay() { Super::BeginPlay(); widget = SNew(SVerticalBox) + SVerticalBox::Slot() .HAlign(HAlign_Center) .VAlign(VAlign_Center) [ SNew(SButton) .Content() [ SNew(STextBlock) .Text(FText::FromString(TEXT("Test button"))) ] ]; GEngine->GameViewport->AddViewportWidgetForPlayer(GetWorld()->GetFirstLocalPlayerFromController(), widget.ToSharedRef(), 1); GetWorld()->GetTimerManager().SetTimer(HUDToggleTimer, FTimerDelegate::CreateLambda ([this] { if (this->widget->GetVisibility().IsVisible()) { this->widget->SetVisibility(EVisibility::Hidden); } else { this->widget->SetVisibility(EVisibility::Visible); } }), 5, true); }
EndPlay
:void AToggleHUDGameMode::EndPlay(constEEndPlayReason::Type EndPlayReason) { Super::EndPlay(EndPlayReason); GetWorld->GetTimerManager().ClearTimer(HUDToggleTimer); }
AToggleHUDGameMode
:As with most of the other recipes in this chapter, we are using a custom GameMode
class to display our single-player UI on the player's viewport for convenience:
BeginPlay
and EndPlay
so that we can correctly handle the timer that will be toggling our UI on and off for us.UPROPERTY
to ensure it won't be garbage collected.BeginPlay
, we create a new VerticalBox
using the SNew
macro, and place a button in its first slot.Content
, which can be some other widget to host inside them, such as SImage
or STextBlock
.STextBlock
into the Content
slot. The contents of the text block are irrelevant as long as they are long enough for us to be able to see our button properly.lambda
function for our toggle the hud function.lambda
function to the timer, we need to create a timer
delegate.FTimerDelegate::CreateLambda
function is designed to convert a lambda
function into a delegate, which the timer can call at the specified interval.lambda
needs to access the this
pointer from its containing object, our GameMode
, so that it can change properties on the widget instance that we have created.lambda
declaration with the []
operators, which enclose variables that should be captured into the lambda
, and accessible inside it.SWidget::SetVisibility
.SetTimer
, we specify the interval (in seconds) to call the timer, and set the timer to loop.BeginPlay
, it makes sense to clear the timer during EndPlay
.EndPlay
will be called whenever GameMode
either ends play or is destroyed, so we can safely cancel the timer during its implementation.GameMode
set as the default game mode, the UI is created when the game begins to play, and the timer delegate executes every 5 seconds to switch the visibility of the widgets between true
and false
.EndPlay
clears the timer reference, avoiding any problems.3.145.107.181