完成本迷你教程之前,請前往完成以下迷你教程:
無前置教程待完成。
本教程適合的人群:
初學者,具有開發經驗兩周;
本示例的目的:為了在代碼中實現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