UE5:C++ 实现 游戏逻辑 ↔ UI 双向联动


观众老爷们大家好 我是邪修KING 欢迎来到我的TA->UE游戏引擎博客---入门篇! C++!高门槛!精选学习! 根据前几篇文章的学习,我们现在已经会蓝图 UI 了,这一篇我们开始直接最标准、最工程化、游戏厂商最常用 的 C++ + UMG 联动方案,一步一步跟着做就能跑通

我们用好现有的项目(玩家立方体、血量、移动速度、UI)直接实现,不用新建项目。

核心一句话

游戏逻辑(C++ Actor)发事件 → UI(C++ UMG)监听事件 → 自动更新界面 这就是 UE 最标准的 解耦架构。

一、整体结构(你必须先看懂)

我们要创建 2 个 C++ 类:

1.PlayerActor.cpp (游戏逻辑:血量、移动、受伤)

2 .PlayerHUD.cpp (UI:显示血量、速度、接收事件更新)

通信方式:

· C++ 多播委托(动态多播) = 蓝图的 "事件分发器"

· UI 绑定委托 → 玩家逻辑调用委托 → UI 自动刷新

二、完整可复制代码(直接用)

1. 玩家 C++ 类(负责游戏逻辑)
MyPlayerActor.h

cpp 复制代码
#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "MyPlayerActor.generated.h"

UCLASS()
class MYPROJECT_API AMyPlayerActor : public AActor
{
    GENERATED_BODY()

public:
    AMyPlayerActor();

protected:
    virtual void BeginPlay() override;

public:
    virtual void Tick(float DeltaTime) override;

    // 血量
    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Health")
    float MaxHealth = 100.0f;

    UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Health")
    float CurrentHealth;

    // 移动速度
    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Movement")
    float MoveSpeed = 500.0f;

    // ==========================================
    // 【关键】委托:血量变化时广播事件
    // ==========================================
    DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnHealthChanged, float, NewHealth);

    UPROPERTY(BlueprintAssignable, Category = "Events")
    FOnHealthChanged OnHealthChanged;

    // 受伤函数
    UFUNCTION(BlueprintCallable, Category = "Health")
    void TakeDamage(float Damage);
};

二、完整代码(直接用)

1. 玩家 C++ 类(负责游戏逻辑)
MyPlayerActor.h

cpp 复制代码
#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "MyPlayerActor.generated.h"

UCLASS()
class MYPROJECT_API AMyPlayerActor : public AActor
{
    GENERATED_BODY()

public:
    AMyPlayerActor();

protected:
    virtual void BeginPlay() override;

public:
    virtual void Tick(float DeltaTime) override;

    // 血量
    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Health")
    float MaxHealth = 100.0f;

    UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Health")
    float CurrentHealth;

    // 移动速度
    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Movement")
    float MoveSpeed = 500.0f;

    // 【关键】委托:血量变化时广播事件
    DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnHealthChanged, float, NewHealth);

    UPROPERTY(BlueprintAssignable, Category = "Events")
    FOnHealthChanged OnHealthChanged;

    // 受伤函数
    UFUNCTION(BlueprintCallable, Category = "Health")
    void TakeDamage(float Damage);
};

MyPlayerActor.cpp

cpp 复制代码
#include "MyPlayerActor.h"

AMyPlayerActor::AMyPlayerActor()
{
    PrimaryActorTick.bCanEverTick = true;
    CurrentHealth = MaxHealth;
}

void AMyPlayerActor::BeginPlay()
{
    Super::BeginPlay();
}

void AMyPlayerActor::Tick(float DeltaTime)
{
    Super::Tick(DeltaTime);
}

void AMyPlayerActor::TakeDamage(float Damage)
{
    CurrentHealth = FMath::Clamp(CurrentHealth - Damage, 0.0f, MaxHealth);

    // 【关键】广播事件 → UI 会收到
    OnHealthChanged.Broadcast(CurrentHealth);
}

2. UI C++ 类(负责显示、接收事件)
MyPlayerHUD.h

cpp 复制代码
#pragma once

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

class AMyPlayerActor;
class UProgressBar;
class UTextBlock;

UCLASS()
class MYPROJECT_API UMyPlayerHUD : public UUserWidget
{
    GENERATED_BODY()

protected:
    virtual void NativeOnInitialized() override;

public:
    // 绑定控件
    UPROPERTY(meta = (BindWidget))
    UProgressBar* HealthBar;

    UPROPERTY(meta = (BindWidget))
    UTextBlock* SpeedText;

    // 玩家引用
    UPROPERTY(EditAnywhere, BlueprintReadWrite)
    AMyPlayerActor* PlayerRef;

    // 更新血量条
    UFUNCTION()
    void UpdateHealth(float NewHealth);

    // 更新速度(每帧)
    void UpdateSpeed();
};

MyPlayerHUD.cpp

cpp 复制代码
#include "MyPlayerHUD.h"
#include "MyPlayerActor.h"
#include "Components/ProgressBar.h"
#include "Components/TextBlock.h"

void UMyPlayerHUD::NativeOnInitialized()
{
    Super::NativeOnInitialized();

    if (PlayerRef)
    {
        // 【关键】UI 绑定玩家的事件
        PlayerRef->OnHealthChanged.AddDynamic(this, &UMyPlayerHUD::UpdateHealth);
    }
}

void UMyPlayerHUD::UpdateHealth(float NewHealth)
{
    if (HealthBar && PlayerRef)
    {
        HealthBar->SetPercent(NewHealth / PlayerRef->MaxHealth);
    }
}

void UMyPlayerHUD::UpdateSpeed()
{
    if (SpeedText && PlayerRef)
    {
        SpeedText->SetText(FText::FromString(
            FString::Printf(TEXT("Move Speed: %.1f"), PlayerRef->MoveSpeed)
        ));
    }
}

三、引擎内操作(5 步完成)

1. 创建 C++ 类

新建 Actor 类 → 命名 MyPlayerActor

新建 UserWidget 类 → 命名 MyPlayerHUD

把上面代码粘贴进去。

2. 创建 UI 控件蓝图(必须继承 C++ 类)

1.右键 → 用户界面 → 控件蓝图

2.父类选择 MyPlayerHUD

3.打开控件蓝图,你会看到:

==HealthBar

==SpeedText

已经自动存在!

直接拖进视口就行,名字必须一样:

==进度条 → 命名 HealthBar

==文本 → 命名 SpeedText

3. 玩家蓝图继承 C++ 类

1.打开你的 BP_CubeTest

2.右上角 类设置

3.父类选择 MyPlayerActor

你的玩家现在变成 C++ 逻辑 + 蓝图编辑

4. 游戏开始时显示 UI

打开玩家 C++ 或蓝图的 BeginPlay:

cpp 复制代码
// C++ 显示 UI
if (UWorld* World = GetWorld())
{
    UMyPlayerHUD* HUD = CreateWidget<UMyPlayerHUD>(World, UMyPlayerHUD::StaticClass());
    if (HUD)
    {
        HUD->PlayerRef = this;
        HUD->AddToViewport();
    }
}

5. 测试:碰撞扣血

在障碍物碰撞时调用:

cpp 复制代码
Player->TakeDamage(20.0f);

四、核心原理(你必须理解)

1. 游戏逻辑 → UI 用 委托(动态多播)

cpp 复制代码
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnHealthChanged, float, NewHealth);
OnHealthChanged.Broadcast(CurrentHealth);

= 蓝图的 事件分发器

2. UI 监听事件

cpp 复制代码
PlayerRef->OnHealthChanged.AddDynamic(this, &UMyPlayerHUD::UpdateHealth);

= 蓝图的 绑定事件
3. 完全解耦

1.玩家不知道 UI 存在

2.UI 不知道玩家内部逻辑

这就是 UE 工程化标准架构

五、总结

1.C++ 扣血 → UI 血量条自动刷新

2.C++ 改速度 → UI 文字实时更新

3.C++ 游戏结束 → UI 显示结束面板

4.UI 按钮点击 → 调用 C++ 暂停游戏

相关推荐
luj_17683 小时前
桥牌思维启示:系统设计的模块化架构
c语言·开发语言·c++·经验分享·算法
会周易的程序员3 小时前
aiDgePLC iec61131 虚拟机 完整使用文档
c++·物联网·架构·st·iec61131
小小龙学IT4 小时前
Boost.Beast 深度实战:基于 Asio 的开源 C++ HTTP/WebSocket 协议库
c++·websocket·http
不可求~5 小时前
C++ std::string_view 不是字符串:从悬空引用到安全用法
java·开发语言·c++
小小龙学IT6 小时前
C++ 正则表达式完全指南:从 std::regex 实战到 RE2 引擎原理(NFA/DFA/回溯陷阱)
c++·正则表达式
码匠许师傅9 小时前
【C++ 面试真题】聊聊 C++ 的序列容器
java·c++·面试
C++ 老炮儿的技术栈9 小时前
Qt5.9.1 Windows 完整开发环境搭建流程
开发语言·c++·windows·qt·编辑器·代码化
欧特克_Glodon9 小时前
OpenCV计算机视觉开发入门与实践<十一>:矩阵的复制和矩形类Rect
c++·opencv·计算机视觉·矩阵
键盘会跳舞10 小时前
C++:std::tuple 源码级深度拆解——变参模板、SFINAE与模板元编程核心技巧
开发语言·c++·sfinae·变参模板
bkspiderx10 小时前
从零开始:VS Code搭建C/C++开发环境全指南(Windows/macOS/Linux)
c语言·c++·windows·vs code·c/c++开发环境