控制反转:让蓝图实现 C++ 的"空洞"

混合开发里最有价值的模式是控制反转:C++ 负责流程骨架,把"表现相关的变化点"留给蓝图实现。两个宏支撑这个模式:BlueprintImplementableEvent(C++ 声明,蓝图实现)和 BlueprintNativeEvent(C++ 有默认实现,蓝图可覆盖)。

// C++ 只声明,不写实现(.cpp 里不能定义 OnDeath)
UFUNCTION(BlueprintImplementableEvent, Category="Combat")
void OnDeath();

// C++ 有默认实现,蓝图可覆盖
UFUNCTION(BlueprintNativeEvent, Category="Combat")
void OnHit(AActor* Damager);
// .cpp 里写 void AMyCharacter::OnHit_Implementation(AActor* Damager) {...}

两者 Grades 的区别:

BlueprintImplementableEvent BlueprintNativeEvent
C++ 实现 无(纯抽象) 有 _Implementation 默认版本
蓝图实现 必须实现才有行为 可覆盖、也可不覆盖
调用成本 蓝图调用走 VM 有 C++ 兜底
适用 表现层必须自己决定 有标准行为、偶尔定制

选型建议:95% 情况用 BlueprintNativeEvent。理由是默认实现保住了"不写蓝图也能跑",这在原型期和测试期非常宝贵。

一个完整例子:受击流程骨架

void AMyCharacter::ApplyDamage(float Amount, AActor* Damager)
{
    // 1. C++ 管规则:伤害结算(不可商量)
    CurrentHealth = FMath::Clamp(CurrentHealth - Amount, 0.f, MaxHealth);

    // 2. C++ 管网络:广播事件
    OnHealthChanged.Broadcast(CurrentHealth);

    // 3. 表现交给蓝图:受击/死亡的具体播放
    if (CurrentHealth <= 0.f)
        OnDeath();            // 蓝图实现:播死亡蒙太奇、生成魂粒子
    else
        OnHit(Damager);       // 蓝图可覆盖:默认播一个通用受击动作
}

这就是混合开发的"骨架-血肉"模式:C++ 定流程与规则,蓝图定表现与手感。策划想让死亡更"燃",自己去改 OnDeath 的蓝图实现,完全不需要程序参与。

注意:调用蓝图事件是跨 VM 边界

每次 C++ 调用 OnDeath() 实际上是进入蓝图虚拟机。因此:

  • 别在每帧 × 大量对象的循环里调蓝图事件;
  • 高频更新用 C++ 委托广播 + 蓝图订阅(第 3 章)代替"每帧调用蓝图事件";
  • 如果某段表现必须高频执行,把数据计算下沉 C++,蓝图只做"播放参数"的最终一步。

本章小结

  • 控制反转是混合开发的灵魂:C++ 造骨架,蓝图填血肉。
  • BlueprintImplementableEvent = 蓝图必须实现;BlueprintNativeEvent = 有 C++ 默认实现、蓝图可覆盖(推荐默认)。
  • 蓝图事件调用跨 VM 边界,避免放在热点循环里。