完成本迷你教程之前,请前往完成以下迷你教程:
无前置教程待完成。
本教程适合的人群:
初学者,具有开发经验两周;
本示例的目的:为了在代码中实现UMG中的这个功能:
说明:这是一些列迷你教程的首篇,所以步骤比较多。
第1步:创建一个FPS(C++)模板工程,我的工程命名为LearnWidgets
第2步:在c++文件夹中找到以下已有的两个类,LearnWidgetsGameMode派生出BPGM,LearnWidgetsHUD派生出BPHUD;并在BPGM中配置HUD为BPHUD;
第3步:
创建一个继承自AActor的类,称为WidgetMng,表示Widget的管理者类,它的功能将会慢慢变强大。
第4步:
在 工程.build.cs 文件中改动代码:
▼代码开始 public LearnWidgets(ReadOnlyTargetRules Target) : base(Target) { PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs; PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "HeadMountedDisplay" //从这一行开始是新增的—————— , "UMG" }); // Uncomment if you are using Slate UI PrivateDependencyModuleNames.AddRange(new string[] { "Slate", "SlateCore" }); //新增结束—————— } ▲代码结束
【实验Tips:如果遇到了无法编译的问题,可以尝试关闭Editor,重启VS,后再build】
第5步:
WidgetMng的代码是这样的:(按照我的风格,我会在代码中写入详细的注释,边看代码边看注释就会明白)
▼代码开始 // Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "CoreMinimal.h" #include "GameFramework/Actor.h" #include "WidgetMng.generated.h" UCLASS() class LEARNWIDGETS_API AWidgetMng : public AActor { GENERATED_BODY() public: // Sets default values for this actor's properties AWidgetMng(); protected: // Called when the game starts or when spawned virtual void BeginPlay() override; public: // Called every frame virtual void Tick(float DeltaTime) override; UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Ws) TSubclassOf<class UUserWidget> SlaveWidgetClass; //这是一个UUserWidget的类目(暴露给蓝图以做选择) UPROPERTY() class UUserWidget* SlaveWidget; //这是真正的UUserWidget实例的指针(当然起初是null) UFUNCTION() void Initialize(); //初始化函数 UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = WsTexture) UTexture2D* T2D; //这是一张纹理UTexture2D,暴露给蓝图以做选择 UFUNCTION() void ChangeImage(UTexture2D* T2D0); //ChangeImage函数希望将它所管理的SlaveWidget中的Image小部件的图片设置为T2D0纹理 UFUNCTION() void ChangeText(const FString & F); //ChangeText函数希望将它所管理的SlaveWidget中的TextBlock小部件的文本设置为F; }; ▲代码结束 以下是cpp文件。 ▼代码开始 // Fill out your copyright notice in the Description page of Project Settings. #include "WidgetMng.h" #include "Runtime/UMG/Public/Blueprint/UserWidget.h" #include "Runtime/UMG/Public/Components/Image.h" #include "Runtime/Engine/Classes/Engine/Texture2D.h" #include "Runtime/UMG/Public/Components/TextBlock.h" //这里要加一些头文件,至于头文件如何加,这里就先不解释了。 // Sets default values AWidgetMng::AWidgetMng() { // 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; } // Called when the game starts or when spawned void AWidgetMng::BeginPlay() { Super::BeginPlay(); } // Called every frame void AWidgetMng::Tick(float DeltaTime) { Super::Tick(DeltaTime); } void AWidgetMng::Initialize() { UE_LOG(LogTemp, Warning, TEXT("%s"), *FString("31 Initialize WidgetMng")); //这是LOG if (SlaveWidgetClass && SlaveWidget==NULL) { SlaveWidget = CreateWidget<UUserWidget>(GWorld->GetGameInstance(), SlaveWidgetClass);//【重要】创建UUserWidget的做法 if (SlaveWidget) { SlaveWidget->AddToViewport();//将此实例加到屏幕上 } } } void AWidgetMng::ChangeImage(UTexture2D* T2D0) { UImage* MyImage = Cast<UImage>(SlaveWidget->GetWidgetFromName(TEXT("MyImage"))); //【重要】从SlaveWidget中找到一个名为MyImage的小部件 if (MyImage) { UE_LOG(LogTemp, Warning, TEXT("%s"), *FString("Changing Image With A T2D")); MyImage->SetBrushFromTexture(T2D0);//【重要】用纹理UTexture2D来设置这个Image小部件 } } void AWidgetMng::ChangeText(const FString & F) {//【重要】这个函数展示了设置特定文本给一个名为MyTextBlock的小部件; UTextBlock* MyTextBlock = Cast<UTextBlock>(SlaveWidget->GetWidgetFromName(TEXT("MyTextBlock"))); if (MyTextBlock) { MyTextBlock->SetText(FText::FromString(F)); } } ▲代码结束
第5+步:在内容浏览器中新建一个UserWidget(命名为WeaponDisplayer)如下:
注意到它有两个小部件,我们命名为MyImage和MyTextBlock;
第6步:找到WidgetMng(Cpp),然后派生一个蓝图名为BPWidgetMng1,
第7步:给BPWidgetMng1中配置白色框框部分(还记得吗,它们是前面步骤暴露出来的):
注意到这里有一张纹理图片叫wenjiezou,你可以import其它的图像文件进来作为纹理;
第8步:
前面写完了WidgetMng(Widget管理者),现在写HUD的逻辑,希望HUD能够生成WidgetMng;然后再生成UserWidget(也就是SlaveWidget)。(分号后面这句话已经编写完逻辑了,现在要做的就是分号前的那个需求)
在LearnWidgetsHUD中,只需要稍微改改代码即可。
LearnWidgetsHUD.h文件:
▼代码开始 // Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. #pragma once #include "CoreMinimal.h" #include "GameFramework/HUD.h" #include "WidgetMng/WidgetMng.h" #include "LearnWidgetsHUD.generated.h" UCLASS() class ALearnWidgetsHUD : public AHUD { GENERATED_BODY() public: ALearnWidgetsHUD(); /** Primary draw call for the HUD */ virtual void DrawHUD() override; private: /** Crosshair asset pointer */ class UTexture2D* CrosshairTex; public: UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = WidgetMngs) TArray<TSubclassOf<AWidgetMng>> WidgetMngsClasses;//【暴露了一些Mngs的类目】 UPROPERTY() TArray<AWidgetMng*> WidgetMngs;//真正的Mngs实例 virtual void BeginPlay() override; }; ▲代码结束 LearnWidgetsHUD.cpp文件: ▼代码开始 // Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. #include "LearnWidgetsHUD.h" #include "Engine/Canvas.h" #include "Engine/Texture2D.h" #include "TextureResource.h" #include "CanvasItem.h" #include "UObject/ConstructorHelpers.h" ALearnWidgetsHUD::ALearnWidgetsHUD() { // Set the crosshair texture static ConstructorHelpers::FObjectFinder<UTexture2D> CrosshairTexObj(TEXT("/Game/FirstPerson/Textures/FirstPersonCrosshair")); CrosshairTex = CrosshairTexObj.Object; } void ALearnWidgetsHUD::DrawHUD() { Super::DrawHUD(); // Draw very simple crosshair // find center of the Canvas const FVector2D Center(Canvas->ClipX * 0.5f, Canvas->ClipY * 0.5f); // offset by half the texture's dimensions so that the center of the texture aligns with the center of the Canvas const FVector2D CrosshairDrawPosition( (Center.X), (Center.Y + 20.0f)); // draw the crosshair FCanvasTileItem TileItem( CrosshairDrawPosition, CrosshairTex->Resource, FLinearColor::White); TileItem.BlendMode = SE_BLEND_Translucent; Canvas->DrawItem( TileItem ); } //只关注这里,这里实例化了WidgetMng void ALearnWidgetsHUD::BeginPlay() { for (auto index = 0; index<WidgetMngsClasses.Num(); index++) { AWidgetMng* NewWidgetMng = NewObject<AWidgetMng>(GetGameInstance(), WidgetMngsClasses[index]); WidgetMngs.Add(NewWidgetMng); NewWidgetMng->Initialize(); } } ▲代码结束
第9步:现在再介绍一个点,就是从PC(playercontroller)指挥这个Mng修改文字或图片。我发现没有PC,只有现成的LearnWidgetsCharacter,所以这里就介绍从Character索引到WidgetMng,其实都差不多;
在LearnWidgetsCharacter中加入代码:
void ALearnWidgetsCharacter::Action1() { UE_LOG(LogTemp, Warning, TEXT("%s"), *FString("Action1 ing")); ALearnWidgetsHUD* HUD = Cast<ALearnWidgetsHUD>(UGameplayStatics::GetPlayerController(this, 0)->GetHUD());//【重要】这是从Character索引到HUD的方法 if (HUD->WidgetMngs.Num()) { HUD->WidgetMngs[0]->ChangeImage(HUD->WidgetMngs[0]->T2D);//【重要】从HUD索引到WidgetMng,调用显示图像函数 } }
然后再讲这个Action1绑定在Action1输入上(如果这个不懂,请学习setupinputcomponent相关的知识);
第10步:
Gamemode是这样的。(如果你不知道什么是Gamemode,请去官网学习Gamemode内容;)
第11步:
按下Action1后(这个Action1是你自己定义的按键噢):
——小江村儿的文杰 zouwj5@qq.com 2017年8月2日14:56:24