实例甜点 Unreal Engine 4迷你教程(1)之如何用C++将纹理绘制在UserWidget的Image小部件上
完成本迷你教程之前,请前往完成以下迷你教程:
无前置教程待完成。
本教程适合的人群:
初学者,具有开发经验两周;
本示例的目的:为了在代码中实现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 = ; 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, )->GetHUD());//【重要】这是从Character索引到HUD的方法
if (HUD->WidgetMngs.Num())
{
HUD->WidgetMngs[]->ChangeImage(HUD->WidgetMngs[]->T2D);//【重要】从HUD索引到WidgetMng,调用显示图像函数
}
}
然后再讲这个Action1绑定在Action1输入上(如果这个不懂,请学习setupinputcomponent相关的知识);
第10步:
Gamemode是这样的。(如果你不知道什么是Gamemode,请去官网学习Gamemode内容;)

第11步:

按下Action1后(这个Action1是你自己定义的按键噢):

——小江村儿的文杰 zouwj5@qq.com 2017年8月2日14:56:24
实例甜点 Unreal Engine 4迷你教程(1)之如何用C++将纹理绘制在UserWidget的Image小部件上的更多相关文章
- 实例甜点 Unreal Engine 4迷你教程(2)之用C++改变Image小部件的颜色
完成本迷你教程之前,请前往完成以下迷你教程: ·实例甜点 Unreal Engine 4迷你教程之如何用C++将纹理绘制在UserWidget的Image小部件上: 目标:实现UMG中的此功能: 在上 ...
- 实例甜点 Unreal Engine 4迷你教程(4)之用C++实现添加子Widget到VerticalBox中以及ClearChildren
前置教程: 1. 实例甜点前面的三篇教程: 2. 最好看看笔者前面的一篇关于博文(后记:本来笔者想用C++做DragAndDrop的功能,但是失败了,下面是蓝图实现的方法): http://www.c ...
- 实例甜点 Unreal Engine 4迷你教程(6)之三个重要基础操作SpawnActor、TArray的Add和Remove
本小节的教程需要完成前置教程:建议阅读<实例甜点 Unreal Engine 4迷你教程(5)>,因为5里面提到了本节的工程,不过也可以在不看5的前提下直接阅读本教程. 第一步:Empty ...
- 实例甜点 Unreal Engine 4迷你教程(3)之用C++改变Image小部件的其它属性
完成本迷你教程之前,请前往完成以下迷你教程: ·实例甜点 Unreal Engine 4迷你教程(2)之用C++改变Image小部件的颜色: 在上一次的迷你教程的LearnWidgets工程上进行(如 ...
- 实例甜点 Unreal Engine 4迷你教程(5)之函数中的静态变量
本小节的教程无前置教程,可直接学习,篇幅很短. 本教程浓缩起来就是一句话:函数中的静态变量在调试过程中保留值.所以需要谨慎对待. 什么意思?请先不要一步一步对着做,而整体地看一遍下面的过程: 第一步: ...
- Unreal Engine 4 系列教程 Part 1:入门
原文:Unreal Engine 4 Tutorial for Beginners: Getting Started 作者:Tommy Tran 译者:Shuchang Liu 本篇教程将引导你安装U ...
- Unreal Engine 4 系列教程 Part 3:材质教程
.katex { display: block; text-align: center; white-space: nowrap; } .katex-display > .katex > ...
- Unreal Engine 4 系列教程 Part 4:UI教程
.katex { display: block; text-align: center; white-space: nowrap; } .katex-display > .katex > ...
- Unreal Engine 4 系列教程 Part 5:制作简单游戏
.katex { display: block; text-align: center; white-space: nowrap; } .katex-display > .katex > ...
随机推荐
- eclipse 下,使用正常模式可以运行,DEBUG模式就卡住的解决方案
最近开发的时候遇到一个问题,就是用运行就可以编译整个项目,但是使用debug模式就卡住了,编译一部分就不动了.开始我以为是项目太大的关系 但是也不至于就DEBUG不行,所以网上差了些资料,原来是DEB ...
- Swift3 访问权限fileprivate和 open
在swift 3中新增加了两种访问控制权限 fileprivate和 open. 下面结合网上资料和个人理解整理一下两个属性的原理与介绍. fileprivate 在原有的swift中的 privat ...
- Xamarin开发笔记—设备类&第三方弹窗的使用和注意事项
一.设备类是Xamarin重要开发组成部分,下面介绍一下设备类的主要用法: //唤醒打电话 Device.OpenUri(new Uri("tel:180xxxxxxxx")); ...
- V9发布内容时保留框架<iframe></iframe>
有些时候,发布文章内容的时候需要用到<iframe></iframe>框架站外内容最近在发布内容时就遇到这个问题,<iframe></iframe>给转 ...
- Linux: 安装NVIDIA显卡驱动
Linux(Fedora25, 64bit)台式机配备了NVIDIA显卡GTX950,但是仅仅使用开源驱动nouveau,无法发挥NVIDIA显卡的性能,所以可以考虑使用官方提供的显卡驱动. # 先安 ...
- java数据类型转换那点事
public class kkk { /** * 先看看eclipse对于数值型转换会有哪些报错,但是有一点必须明确,eclipse不报错的,不一定就是说这种思维逻辑是对的 * 可以直接将代码复制过去 ...
- js中数学运算的处理
connum = Number(connum) + Number($(this).parents('.123').find(".views_core_hidden").val()) ...
- MySQL删除表方式差异
数据库删除语句 Drop/Delete/Truncate比较 Delete :删除数据表中的行(可以删除某一行,也可以在不删除数据表的情况下删除所有行). 删除某一行:Delete from 数据表名 ...
- 使用javac编译zookeeper项目
这里记录zookeeper编译源代码上的一些细节的问题. 网上不少关于如何使用ant eclipse来构建zookeeper对应的eclipse工程的记录.这里就不再过多赘述.只做简单阐述. 这里主要 ...
- RADIUS and IPv6[frc-3162译文]
如今项目中需要涉及到RADIUS及IPv6的使用,而网络中的资料相对较少,现对frc-3162进行中文翻译,分享出来. 由于英语水平有限,翻译不恰当的地方,还请提出,便于在下及时修改. 原文链接 这份 ...