|
Unreal Engine 4 C Slate 介绍用C和Slate创建菜单三
Unreal Engine 4 C++ Slate 介绍——用C++和Slate创建菜单(三)
好记性不如烂笔头啊,还是记录一下!
欢迎回到我的使用Slate和C++在虚幻引擎4中创建菜单的教程系列!
第一步:概述和准备
什么是数据绑定? 数据绑定是一种来自软件开发的概念,其中信息输出(例如玩家的当前血量)与实际展示的信息相关联。这样,只要更改数据(例如,对玩家造成伤害),显示就会自动更新。
在我们的示例中,我们将创建一个新的Slate UI,用作游戏中的HUD,在屏幕的上角显示玩家的当前血量和得分。最初,HUD将只有静态值 - 我们将在下一步中将其更改为绑定数据。 我将粘贴下面的代码,但不会详细介绍它是如何工作的 - 这是所有很简单的内容,已经在过去的教程中已经讲过了。
// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.// TutorialGameHUDUI.h - Provides an implementation of the Slate UI representing the tutorial game HUD.#pragma once#include "Slate.h"// Lays out and controls the Tutorial HUD UI.class STutorialGameHUDUI : public SCompoundWidget{ SLATE_BEGIN_ARGS(STutorialGameHUDUI) : _OwnerHUD() { } SLATE_ARGUMENT(TWeakObjectPtr<class ATutorialGameHUD>, OwnerHUD); SLATE_END_ARGS()public: /** * Constructs and lays out the Tutorial HUD UI Widget. * * \args Arguments structure that contains widget-specific setup information. **/void Construct(const FArguments& args);private: /** * Stores a weak reference to the HUD owning this widget. **/ TWeakObjectPtr<class ATutorialGameHUD> OwnerHUD; /** * A reference to the Slate Style used for this HUD's widgets. **/conststruct FGlobalStyle* HUDStyle;};
// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.#include "SlateTutorials.h"#include "TutorialGameHUD.h"#include "TutorialGameHUDUI.h"#include "Menus/GlobalMenuStyle.h"#include "Menus/MenuStyles.h"void STutorialGameHUDUI::Construct(const FArguments& args){ OwnerHUD = args._OwnerHUD; HUDStyle = &FMenuStyles::Get().GetWidgetStyle<FGlobalStyle>("Global"); ChildSlot [ SNew(SOverlay) + SOverlay::Slot() .HAlign(HAlign_Right) .VAlign(VAlign_Top) [ SNew(STextBlock) .TextStyle(&HUDStyle->MenuTitleStyle) .Text(FText::FromString("SCORE: 0")) ] + SOverlay::Slot() .HAlign(HAlign_Left) .VAlign(VAlign_Top) [ SNew(STextBlock) .TextStyle(&HUDStyle->MenuTitleStyle) .Text(FText::FromString("HEALTH: 100")) ] ];}
// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.// TutorialGameHUD.h - Provides an implementation of the HUD that will embed the Tutorial Game UI.#pragma once#include "GameFramework/HUD.h"#include "TutorialGameHUD.generated.h"/** * Provides an implementation of the game's in-game HUD, which will display the player's current health and score. **/UCLASS()class ATutorialGameHUD : public AHUD{ GENERATED_UCLASS_BODY()public: /** * Initializes the Slate UI and adds it as a widget to the game viewport. **/virtualvoid PostInitializeComponents() override;private: /** * Reference to the Game HUD UI. **/ TSharedPtr<class STutorialGameHUDUI> GameHUD;};
// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.#include "SlateTutorials.h"#include "TutorialGameHUD.h"#include "TutorialGameHUDUI.h"ATutorialGameHUD::ATutorialGameHUD(constclass FPostConstructInitializeProperties& PCIP) : Super(PCIP){}void ATutorialGameHUD::PostInitializeComponents(){ Super::PostInitializeComponents(); if (GEngine && GEngine->GameViewport) { UGameViewportClient* Viewport = GEngine->GameViewport; SAssignNew(GameHUD, STutorialGameHUDUI) .OwnerHUD(TWeakObjectPtr<ATutorialGameHUD>(this)); Viewport->AddViewportWidgetContent( SNew(SWeakWidget).PossiblyNullContent(GameHUD.ToSharedRef()) ); }}继续构建项目并设置一个新的地图和游戏模式,并让HUD显示出来!
第二步:绑定数据
我们有两个信息需要显示,我们想绑定到我们的UI:得分和血量。这两个都是整数,但它们必须绑定为我们的HUD的字符串!我们很快会从游戏模式(积分)和角色(血量)获取此信息,但首先我们将处理数据绑定部分。我们的绑定将有两个重要的任务:第一,它将获取实际数据。接下来,它会将其转换为要应用于文本块控件的FText。
他们都需要两个东西:属性和绑定它的东西。在我们的例子中,因为我们需要对数据进行额外的处理(从一个整数转换为一个字符串),我们将在我们的widget类本身有一个函数来绑定。 将以下私有属性值和方法添加到STutorialGameHUDUI类中:
// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.// TutorialGameHUDUI.h - Provides an implementation of the Slate UI representing the tutorial game HUD.#pragma once#include "Slate.h"// Lays out and controls the Tutorial HUD UI.class STutorialGameHUDUI : public SCompoundWidget{ SLATE_BEGIN_ARGS(STutorialGameHUDUI) : _OwnerHUD() { } SLATE_ARGUMENT(TWeakObjectPtr<class ATutorialGameHUD>, OwnerHUD); SLATE_END_ARGS()public: /** * Constructs and lays out the Tutorial HUD UI Widget. * * \args Arguments structure that contains widget-specific setup information. **/void Construct(const FArguments& args);private: /** * Stores a weak reference to the HUD owning this widget. **/ TWeakObjectPtr<class ATutorialGameHUD> OwnerHUD; /** * A reference to the Slate Style used for this HUD's widgets. **/conststruct FGlobalStyle* HUDStyle;private: /** * Attribute storing the binding for the player's score. **/ TAttribute<FText> Score; /** * Attribute storing the binding for the player's health. **/ TAttribute<FText> Health; /** * Our Score will be bound to this function, which will retrieve the appropriate data and convert it into an FText. **/ FText GetScore() const; /** * Our Health will be bound to this function, which will retrieve the appropriate data and convert it into an FText. **/ FText GetHealth() const; };在虚幻中使用TAttribute类型来提供有一个accessor/getter的数据绑定。 接下来,我们有两个常量函数,负责检索和格式化数据到UI可以使用的类型!那么我们如何实际做绑定? 好吧,它很简单 - 事实上,如果你在C++中为Unreal项目完成了输入绑定,你已经做到了。 在STutorialGameHUDUI的Construct方法的顶部,在捕获HUDStyle之后,添加以下内容将我们的TAttributes绑定到它们适当的函数:
Score.Bind(this, &STutorialGameHUDUI::GetScore);Health.Bind(this, &STutorialGameHUDUI::GetHealth);接下来,我们在UI布局中直接使用TAttributes类型:
+ SOverlay::Slot() .HAlign(HAlign_Right) .VAlign(VAlign_Top) [ SNew(STextBlock) .TextStyle(&HUDStyle->MenuTitleStyle) .Text(Score) ]+ SOverlay::Slot() .HAlign(HAlign_Left) .VAlign(VAlign_Top) [ SNew(STextBlock) .TextStyle(&HUDStyle->MenuTitleStyle) .Text(Health) ]最后,我们要在绑定函数放入一些临时数据,只是为了确保一切正常工作:
FText STutorialGameHUDUI::GetScore() const { return FText::FromString("SCORE: --"); }FText STutorialGameHUDUI::GetHealth() const { return FText::FromString("HEALTH: --"); }继续编译肯定一切正常,恭喜你!你刚刚绑定了你的文本块! 您可以对Slate的所有内容执行此绑定 - 按钮文本,列表项,图像背景,样式等。
第三步:有用的数据
如果你只需要学习如何做数据绑定,而不关心本教程的细节,那么你可以跳过本节 - 在这里,我们只是实现了分数和血量功能。
为了获得本教程的得分和血量数据,我添加了以下GameMode和Character类,并将它们设置为与GameMap关卡一起使用。
// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.// TutGameMode.h - Provides a simple game mode providing a Score!#pragma once#include "GameFramework/GameMode.h"#include "TutGameMode.generated.h"/** * A simple game mode providing a means of retrieving and adjusting a single Score value. **/UCLASS()class ATutGameMode : public AGameMode{ GENERATED_UCLASS_BODY()public: /** * Retrieves the current Score from the game mode. **/ UFUNCTION(BlueprintPure, BlueprintCallable, Category = "Score") int32 GetScore(); /** * Adds to the game score. **/ UFUNCTION(BlueprintCallable, Category = "Score") void AddPoints(int32 value); /** * Removes from the game score. **/ UFUNCTION(BlueprintCallable, Category = "Score") void DeductPoints(int32 value);private: /** * Stores the current score. **/ int32 CurrentScore;};
// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.#include "SlateTutorials.h"#include <algorithm>#include "TutGameMode.h"ATutGameMode::ATutGameMode(constclass FPostConstructInitializeProperties& PCIP) : Super(PCIP), CurrentScore(0){}int32 ATutGameMode::GetScore(){ return CurrentScore;}void ATutGameMode::AddPoints(int32 value){ if (value > 0) CurrentScore += value;}void ATutGameMode::DeductPoints(int32 value){ if (value > 0) CurrentScore = std::max(CurrentScore - value, 0);}
// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.// TutorialCharacter.h - Provides a simple character providing Health!#pragma once#include "GameFramework/Character.h"#include "TutorialCharacter.generated.h"/** * A simple character providing a means of retrieving and manipulating health. **/UCLASS()class ATutorialCharacter : public ACharacter{ GENERATED_UCLASS_BODY()public: /** * Stores the character's current health. **/ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Combat") int32 Health;};
// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.#include "SlateTutorials.h"#include "TutorialCharacter.h"ATutorialCharacter::ATutorialCharacter(constclass FPostConstructInitializeProperties& PCIP) : Super(PCIP){ Health = 100;}一旦我们有了这些,更新得分和血量的数据是很简单的;
FText STutorialGameHUDUI::GetScore() const{ // NOTE: THIS IS A TERRIBLE WAY TO DO THIS. DO NOT DO IT. IT ONLY WORKS ON SERVERS. USE GAME STATES INSTEAD! ATutGameMode* gameMode = Cast<ATutGameMode>(OwnerHUD->GetWorldSettings()->GetWorld()->GetAuthGameMode()); if (gameMode == nullptr) return FText::FromString(TEXT("SCORE: --")); FString score = TEXT("SCORE: "); score.AppendInt(gameMode->GetScore()); return FText::FromString(score);}FText STutorialGameHUDUI::GetHealth() const { ATutorialCharacter* character = Cast<ATutorialCharacter>(OwnerHUD->PlayerOwner->GetCharacter()); if (character == nullptr) return FText::FromString(TEXT("HEALTH: --")); FString health = TEXT("HEALTH: "); health.AppendInt(character->Health); return FText::FromString(health);}继续并运行游戏,然后更新得分!(您可以在示例文件中通过按Home/End来调整血量,然后按Page Up/Page Down来调整分数)。示例文件下载地址:File:SlateTutorials-3.zip |
|