控制反转:让蓝图实现 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 边界,避免放在热点循环里。
