AgentSkillsCN

Cpp Widgets

创建UE5 UMG控件、进行UI开发,或使用BindWidget功能。

SKILL.md
--- frontmatter
description: Creating UE5 UMG widgets, UI development, or using BindWidget

UE5 C++ Widgets (UMG)

Best practices for creating UMG widgets with C++ logic and Blueprint visuals.

Architecture Pattern

Logic in C++, visuals in Widget Blueprints

cpp
// C++ base class handles logic
UCLASS(Abstract)  // Prevent direct instantiation
class MYGAME_API UHealthBarWidget : public UUserWidget
{
    GENERATED_BODY()

protected:
    // Required binding - compilation fails if missing in BP
    UPROPERTY(meta = (BindWidget))
    TObjectPtr<UProgressBar> HealthBar;

    // Optional binding - no error if missing
    UPROPERTY(meta = (BindWidgetOptional))
    TObjectPtr<UTextBlock> HealthLabel;

    // Add BlueprintReadOnly for Graph access
    UPROPERTY(BlueprintReadOnly, meta = (BindWidget))
    TObjectPtr<UImage> DamageFlashImage;

public:
    void SetHealthPercent(float Percent);
};

Naming Conventions

TypeC++ NameBlueprint Name
Widget C++ classUHealthBarWidget-
Widget Blueprint-WBP_HealthBar
Custom base classUBUIUserWidget-

Widget Property Suffixes

SuffixWidget Type
LabelUTextBlock
PanelContainer widgets (UCanvasPanel, UVerticalBox)
ImageUImage
ButtonUButton
BarUProgressBar

BindWidget Rules

cpp
// Names MUST match exactly between C++ and Blueprint
UPROPERTY(meta = (BindWidget))
TObjectPtr<UProgressBar> HealthBar;  // BP widget must be named "HealthBar"

UPROPERTY(meta = (BindWidgetOptional))
TObjectPtr<UTextBlock> ScoreLabel;  // Optional, won't fail if missing

Base Class Hierarchy

Create intermediate base classes for project-wide functionality:

cpp
// Project base widget - between UUserWidget and implementations
UCLASS(Abstract)
class MYGAME_API UBUIUserWidget : public UUserWidget
{
    GENERATED_BODY()

protected:
    // Shared functionality for all project widgets
    virtual void NativeConstruct() override;
};

// Subclass custom widgets from project base
UCLASS(Abstract)
class MYGAME_API UBUIButton : public UButton
{
    GENERATED_BODY()
    // Custom button behavior
};

Performance

AvoidUse Instead
Bind functions (execute every frame)NativeTick or event-driven updates
Tick for all widgetsEvents and delegates
Frequent widget creationWidget pooling
cpp
// AVOID - Bind runs every frame
// Widget Bind -> GetHealthPercent()

// PREFER - Event-driven
void UHealthComponent::TakeDamage(float Amount)
{
    Health -= Amount;
    OnHealthChanged.Broadcast(Health / MaxHealth);  // Update only when changed
}

Common Setup

cpp
// HealthBarWidget.h
UCLASS(Abstract)
class UHealthBarWidget : public UBUIUserWidget
{
    GENERATED_BODY()

public:
    UFUNCTION(BlueprintCallable)
    void SetHealth(float Current, float Max);

protected:
    virtual void NativeConstruct() override;

    UPROPERTY(meta = (BindWidget))
    TObjectPtr<UProgressBar> HealthBar;

    UPROPERTY(meta = (BindWidgetOptional))
    TObjectPtr<UTextBlock> HealthLabel;
};

Documentation: https://dev.epicgames.com/documentation/en-us/unreal-engine/umg-ui-designer-for-unreal-engine