【Unreal】使用 BindWidget 将 C++ 连接到 UMG 蓝图

在这里插入图片描述
如果您开始制作基于 C++ 的 UI,您将遇到的最常见问题之一是:

  • 如何从 C++ 控制蓝图创建的小部件?

答案是BindWidget元属性。

基本 BindWidget 示例

UPROPERTY(BlueprintReadWrite, meta = (BindWidget))
class UTextBlock* TitleLabel;

UPROPERTY(BlueprintReadWrite, meta = (BindWidget))
class UImage* IconImage;

虽然UPROPERTY()文档中没有提到它,但它是作为 UI 开发人员的最有用的标签之一。

顺便说一句,请查看我的完整 UPROPERTY 文档,其中包括所有属性BindWidget和其他属性。

通过将指向小部件的指针标记为BindWidget,您可以在 C++ 类的蓝图子类中创建 同名小部件,并在运行时从 C++ 访问它。

这是使测试正常工作的分步过程:

  1. 创建.UUserWidget
  2. 在其中添加一个成员变量UWidget或它的子类(例如UImage*,UTextBlock等)
  3. UPROPERTY(meta=(BindWidget)) 标记它。
  4. 运行编辑器并创建 C++ 类的蓝图子类。
  5. 创建一个与您的成员变量具有相同类型和确切名称的小部件。
  6. 您现在可以从 C++ 访问小部件。

如果这些步骤中的任何一个没有意义,请查看我关于使用 Unreal 制作 UI 的介绍系列

示例代码

BindExample.h

#pragma once 

#include "CoreMinimal.h"
#include "Blueprint/UserWidget.h"
#include "BindExample.generated.h"

UCLASS(Abstract)
class UBindExample : public UUserWidget
{
	GENERATED_BODY()

protected:
	virtual void NativeConstruct() override;

	UPROPERTY(BlueprintReadOnly, meta=(BindWidget))
	class UTextBlock* ItemTitle;
};

BindExample.cpp

#include "BindExample.h"
#include "Components/TextBlock.h"

void UBindExample::NativeConstruct()
{
	Super::NativeConstruct();

	// ItemTitle can be nullptr if we haven't created it in the
	// Blueprint subclass
	if (ItemTitle)
	{
		ItemTitle->SetText(FText::FromString(TEXT("Hello world!")));
	}
}

现在编译 C++ 并打开添加ItemTitle属性的 C++ 类的蓝图子类。ItemTitle如果您编译蓝图,如果您的 UserWidget中没有命名 TextBlock 小部件,则会显示错误。

使用缺少 BindWidget 标记的属性编译蓝图
在这里插入图片描述
如果我们现在添加一个 Text 小部件并更改其名称以匹配我们的 C++ 文件,则此编译错误将消失,并且当我们运行游戏时,文本将更改为“Hello world!”。

具有正确命名的文本块的蓝图
在这里插入图片描述

使用BindWidget和 C++的优缺点

为什么我们要使用BindWidgetC++ 而不仅仅是在蓝图中编写所有逻辑?

  • 更容易在 C++ 中维护复杂的逻辑。蓝图中没有意大利面条式的战斗。
  • 协作更轻松,无需担心锁定蓝图资产。
  • 需要重新编译才能看到更改。使用 Live Coding 可以在一定程度上避免这种时间成本。
  • 当逻辑从蓝图转移到 C++ 时,非程序员更难看到数据是如何填充的。

可选小部件

在某些情况下,您可能有一个基础 C++ 类和它的许多不同的蓝图子类。例如,一个基本按钮类在 C++ 中可能具有通用逻辑,但您可以创建许多不同的蓝图子类,为每种视觉样式创建一个子类。一些视觉样式可能有图标,另一些可能有文本,因此将文本和图标图像小部件设为可选是有意义的。

要使小部件可选使用meta=(BindWidgetOptional). 这样,如果 Blueprint 类没有具有该名称的小部件,则不会显示错误。

BindWidget可选示例

UPROPERTY(BlueprintReadWrite, meta=(BindWidgetOptional))
UTextBlock* ButtonLabel;

UPROPERTY(BlueprintReadWrite, meta=(BindWidgetOptional))
UImage* IconImage;

BindWidget的怪处

  • 编译一个没有被BindWidget标记过的 widget 的蓝图将显示错误。但是仍然可以运行您的游戏。如果您想避免在这种情况下发生崩溃,您需要检查该变量是否不是nullptr.
  • 通常,当在 UserWidget 上勾选“Is Variable”标志时,它会在编辑器的 Graph 选项卡中可用。但是,如果存在具有该名称的属性,标记为BindWidget,则使其在蓝图中可访问的唯一方法是将其添加BlueprintReadOnly或添加BlueprintReadWrite到其**UPROPERTY()**标记中。
  • 默认情况下,父 C++类中定义的变量仅在选中“显示继承的变量”时才会显示在变量列表中(参见屏幕截图)。
  • BindWidget标记过的 widget 在 C++ 构造函数中为空,它们稍后在生命周期中被初始化。如果您需要进行类似构造函数的设置,请使用该**NativeConstruct()**函数。

显示在父 C++ 类中定义的变量
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值