参考文章:
UMG按钮事件实现
UI绑定
在C++中设置UMG的样式并不方便,我们选择在蓝图中设置样式,然后在C++中实现方法
创建一个继承于
UserWidget
的C++类和蓝图类
然后根据创建好的C++类,生成一个对应的蓝图类
[!Warning]
在蓝图类中编辑好对应的样式,注意左侧按钮的命名,要与在C++中的变量名相同
MyUserWidget.h
public:
// 定时器句柄
FTimerHandle TimerHandle;
UPROPERTY(meta=(BindWidget))
class UButton* Button_Start;
UPROPERTY(meta=(BindWidget))
class UButton* Button_Set;
UPROPERTY(meta=(BindWidget))
class UButton* Button_Quit;
virtual void NativeConstruct() override;
UFUNCTION()
void Delay();
UFUNCTION()
void OnClickedStart();
UFUNCTION()
void OnClickedQuit();
class AAStar_test2Character* player;
class APlayerController* FirstPlayerController;
在cpp中绑定按钮的点击事件UMyUserWidget.cpp
void UMyUserWidget::NativeConstruct()
{
Super::NativeConstruct();
Button_Start->OnClicked.AddDynamic(this, &UMyUserWidget::OnClickedStart);
Button_Quit->OnClicked.AddDynamic(this, &UMyUserWidget::OnClickedQuit);
}
按钮的点击方法实现
void UMyUserWidget::OnClickedStart()
{
RemoveFromParent();
// find player who`s type is AAStar_test2Character
player = nullptr;
for (TActorIterator<AAStar_test2Character> It(GetWorld()); It; ++It)
{
player = *It;
// 返回true,是同一个类型
if (player->IsA(AAStar_test2Character::StaticClass())) UE_LOG(LogTemp, Warning, TEXT("是同一个类型,%s"),*player->GetName());
if (player && player->GetName().Contains("BP_TopDownCharacter"))
{
UE_LOG(LogTemp, Warning, TEXT("Found BP_TopDownCharacter: %s"), *player->GetName());
break;
}
}
if (!player)
{
UE_LOG(LogTemp, Warning, TEXT("未找到名为 BP_TopDownCharacter 的 Actor"));
}
UE_LOG(LogTemp, Warning, TEXT("the type of player is : %s"), *player->GetName());
// getPlayerController
FirstPlayerController = GetWorld()->GetFirstPlayerController();
FirstPlayerController->SetViewTargetWithBlend(player, 1.0f);
GetWorld()->GetTimerManager().SetTimer(TimerHandle,this,&UMyUserWidget::Delay,1.0f,false);
}
void UMyUserWidget::Delay()
{
UE_LOG(LogTemp, Log, TEXT("delay 1 second"));
FirstPlayerController->Possess(player);
FirstPlayerController->SetShowMouseCursor(true);
}
void UMyUserWidget::OnClickedQuit()
{
UKismetSystemLibrary::QuitGame(GetWorld(), nullptr, EQuitPreference::Quit, false);
}
在关卡蓝图中设置UMG的出现
设置开始的摄像头,创建一个pawn类型的蓝图,然后在蓝图中仅放置一个摄像机,放置在直接中,设置posses为player0即可。参考【虚幻4】UE4初学者系列教程合集-全中文新手入门教程
实现效果
UI动画和暂停游戏
与个UMG同理,创建一个继承自
UserWidget
的C++类,并生成对应的蓝图类
暂停UMG的逻辑实现
Pause.h
// 定时器句柄
FTimerHandle TimerHandle;
// 绑定按钮
UPROPERTY(meta=(BindWidget))
class UButton* Quit;
// 绑定按钮
UPROPERTY(meta=(BindWidget))
class UButton* Continue;
// 绑定动画
UPROPERTY(meta = (BindWidgetAnim), Transient)
class UWidgetAnimation* Appear;
virtual void NativeConstruct() override;
UFUNCTION()
void OnClickedContinue();
UFUNCTION()
void OnClickedQQuit();
UFUNCTION()
void PlayTheAnimation();
UFUNCTION()
void PauseDelay();
class AAStar_test2Character* player;
class APlayerController* FirstPlayerController;
Pause.cpp
void UPause::NativeConstruct()
{
Super::NativeConstruct();
if (Continue)
Continue -> OnClicked.AddDynamic(this, &UPause::OnClickedContinue);
else UE_LOG(LogTemp, Log, TEXT("Continue is not alive"));
if (Quit)
Quit -> OnClicked.AddDynamic(this, &UPause::OnClickedQQuit);
else UE_LOG(LogTemp, Log, TEXT("Quit is not alive"));
}
void UPause::OnClickedContinue()
{
UE_LOG(LogTemp, Warning, TEXT("触发OnClickedContinue"));
FirstPlayerController = GetWorld()->GetFirstPlayerController();
// FirstPlayerController -> SetShowMouseCursor(false);
FirstPlayerController -> SetInputMode(FInputModeGameOnly());
UGameplayStatics::SetGamePaused(GetWorld(),false);
PlayAnimation(Appear, 0.0f, 1, EUMGSequencePlayMode::Reverse, 0.75f, true);
GetWorld()->GetTimerManager().SetTimer(TimerHandle,this,&UPause::PauseDelay,0.75f,false);
}
void UPause::PauseDelay()
{
SetVisibility(ESlateVisibility::Collapsed);
StopAnimation(Appear);
}
void UPause::PlayTheAnimation()
{
// InAnimation, StartAtTime = 0.0f,NumLoopsToPlay = 1, EUMGSequencePlayMode::Type PlayMode = EUMGSequencePlayMode::Forward, float PlaybackSpeed = 1.0f, bool bRestoreState = false)
PlayAnimation(Appear, 0.0f, 1, EUMGSequencePlayMode::Forward, 0.75f, true);
}
void UPause::OnClickedQQuit()
{
UKismetSystemLibrary::QuitGame(GetWorld(), nullptr, EQuitPreference::Quit, false);
}
在playerController中设置相关事件
主要包括Widget的初始化和键盘事件的绑定和触发
PlayerController.h
// 绑定按钮使用
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category=Input, meta=(AllowPrivateAccess = "true"))
UInputAction* SetInputQAction;
// 创建Widget使用
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (AllowPrivateAccess = "true"))
TSubclassOf<class UPause> PauseWidgetClass;
UPROPERTY()
class UPause* PauseWidget;
private:
// 设置初始化Widget
void SetupPauseWidget();
// 点击事件触发
void OnPause();
PlayerController.cpp
void AAStar_test2PlayerController::BeginPlay()
{
// Call the base class
Super::BeginPlay();
SetupPauseWidget();
}
void AAStar_test2PlayerController::SetupPauseWidget()
{
if (PauseWidgetClass)
{
UE_LOG(LogTemp, Warning, TEXT("PauseWidgetClass存在"));
PauseWidget = CreateWidget<UPause>(this, PauseWidgetClass);
if (PauseWidget)
{
UE_LOG(LogTemp, Warning, TEXT("PauseWidget存在"));
PauseWidget->AddToViewport();
PauseWidget->SetVisibility(ESlateVisibility::Collapsed);
}
}
}
void AAStar_test2PlayerController::OnPause()
{
UE_LOG(LogTemp, Warning, TEXT("按Q,开始执行Pause"));
bool isPlaying = PauseWidget -> IsAnimationPlaying(PauseWidget->Appear);
if (!isPlaying)
{
UE_LOG(LogTemp, Warning, TEXT("没有播放动画,走动画"));
UE_LOG(LogTemp, Warning, TEXT("%s"), *PauseWidget->GetName());
PauseWidget -> SetVisibility(ESlateVisibility::Visible);
PauseWidget -> PlayTheAnimation();
APlayerController* FirstPlayerController = GetWorld()->GetFirstPlayerController();
// FirstPlayerController->SetShowMouseCursor(true);
FirstPlayerController->SetInputMode(FInputModeUIOnly());
UGameplayStatics::SetGamePaused(GetWorld(),true);
}
}
// 绑定暂停键 Q
void AAStar_test2PlayerController::SetupInputComponent()
{
// set up gameplay key bindings
Super::SetupInputComponent();
// Add Input Mapping Context
if (UEnhancedInputLocalPlayerSubsystem* Subsystem = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(GetLocalPlayer()))
{
Subsystem->AddMappingContext(DefaultMappingContext, 0);
}
// Set up action bindings
if (UEnhancedInputComponent* EnhancedInputComponent = Cast<UEnhancedInputComponent>(InputComponent))
{
// 绑定暂停键 Q
EnhancedInputComponent->BindAction(SetInputQAction, ETriggerEvent::Started, this, &AAStar_test2PlayerController::OnPause);
}
else
{
UE_LOG(LogTemplateCharacter, Error, TEXT("'%s' Failed to find an Enhanced Input Component! This template is built to use the Enhanced Input system. If you intend to use the legacy system, then you will need to update this C++ file."), *GetNameSafe(this));
}
}
蓝图上的设置
UI界面的设置参考:https://www.bilibili.com/video/BV164411Y732?spm_id_from=333.788.videopod.episodes&vd_source=6d070e5f2a4f28fd128440195fce3d9a&p=63
因为使用的是UE5的增强输入,故按键的绑定事件需要额外添加蓝图文件
首先新建一个输入操作
找到对应的全局InputMappingContext(IMC),在里面添加新的操作
最后绑定输入操作到IMC中,在PlayerController的细节面板中,绑定即可。同时我这里绑定了在PlayerController.h中创建的TSubclassOf PauseWidgetClass;