C++ 委托与蓝图事件的配合
把上两页的内容放进一个真实流程里看:"玩家被攻击 → 扣血 → UI 更新 → 判定死亡"。
分层实现
// C++:血量组件(只管规则与广播)
UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent))
class UHealthComponent : public UActorComponent
{
GENERATED_BODY()
public:
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnHealthChanged, float, NewHealth);
UPROPERTY(BlueprintAssignable, Category="Health")
FOnHealthChanged OnHealthChanged;
UFUNCTION(BlueprintCallable, Category="Health")
void ApplyDamage(float Amount);
};
void UHealthComponent::ApplyDamage(float Amount)
{
CurrentHealth = FMath::Clamp(CurrentHealth - Amount, 0.f, MaxHealth);
OnHealthChanged.Broadcast(CurrentHealth); // ← 广播给蓝图
if (CurrentHealth <= 0.f) OnDeath.Broadcast(); // 死亡广播
}
蓝图(角色 BP_PlayerCharacter):
Event OnHealthChanged (NewHealth)
→ 设置 UMG 血条 Widget 的百分比
→ 屏幕边缘红色受击特效(Delay 0.2s 后隐藏)
蓝图(UI 控制器):
Event OnDeath → 播放死亡蒙太奇、弹出结算面板
规则在 C++(血量计算不可绕过),表现在蓝图(UI、特效、动画随策划调)。这就是混合开发的教科书形态。
蓝图订阅 vs 蓝图实现事件的区别
新人容易混的两个概念:
| 蓝图事件(BlueprintNativeEvent 等) | 订阅广播(Bind Event) | |
|---|---|---|
| 触发者 | C++ 直接调用"这个对象的方法" | C++ 广播,任何订阅者都能收 |
| 关系 | 一对一(父子类覆盖) | 一对多 |
| 典型 | OnDeath() 这种"对象自己的行为" |
OnHealthChanged 这种"对外通知" |
口诀:"对象自己的行为"用可重载事件;"对外通知"用广播。
注意:绑定的时机
蓝图在 Event BeginPlay 时绑定广播是常见做法,但如果广播发生在 BeginPlay 之前(如 C++ 构造函数里),订阅者会错过。解决方案:把首次"同步状态"单独做一次——订阅后主动调一次 Update 函数,而不是指望广播补发。
本章小结
- 典型分层:C++ 组件管规则 + 广播事件;蓝图层订阅并表现。
- 可重载事件用于"对象自身行为",广播用于"对外通知",两者各司其职。
- 绑定时机问题:订阅后主动同步一次状态,别依赖广播补发。
