实战:角色与武器的通信架构
把本章四种手段放进一个具体系统里。
需求
- 武器可拾取、装备、攻击;
- 武器攻击命中敌人 → 敌人扣血;
- UI 要显示当前武器与弹药;
- 换武器要有表现(动画、音效)。
架构设计
C++ 层
UWeaponComponent(角色持有) —— 拥有当前武器、管理装备流程
AWeaponBase(Actor) —— 武器基类,含 USkeletalMeshComponent
BPI_Damageable(接口) —— 可受伤者的统一契约
UHealthComponent(血量组件) —— 规则与 OnHealthChanged 广播(上页已写)
蓝图层
BP_Weapon_Sword、BP_Weapon_Bow —— 继承 AWeaponBase,各自表现
WBP_WeaponHUD —— 订阅 OnWeaponChanged 刷新显示
三个关键通信点
① 角色通知 UI"换武器了"(一对多 → 广播)
// UWeaponComponent
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnWeaponChanged, AWeaponBase*, NewWeapon);
UPROPERTY(BlueprintAssignable) FOnWeaponChanged OnWeaponChanged;
void UWeaponComponent::Equip(AWeaponBase* W)
{
if (CurrentWeapon) CurrentWeapon->OnUnequip(); // 接口/事件:旧武器收起
CurrentWeapon = W;
CurrentWeapon->OnEquip(); // 新武器装备表现
OnWeaponChanged.Broadcast(W); // 通知 UI
}
② 武器命中敌人(不认识具体敌人 → 接口)
// AWeaponBase::OnHit 里
if (IDamageable* D = Cast<IDamageable>(HitActor))
{
FDamageInfo Info; Info.Amount = Damage; Info.Instigator = GetOwner();
D->ApplyDamage_Implementation(Info); // 走接口,不知对方是小怪还是Boss
}
③ 敌人扣血通知 UI(上页已有:HealthComponent 广播)
为什么这样分层
- 武器不知道"敌人是谁" → 接口,加新敌人无成本;
- UI 不知道"武器怎么换" → 广播订阅,UI 换皮不动武器逻辑;
- 规则全部在 C++(扣血、装备状态机)→ 性能与正确性有保障;
- 表现全在蓝图(蒙太奇、音效、UI 动画)→ 美术策划自己迭代。
常见演进:网络化后怎么办?
单机版架构做好后,要加多人:ApplyDamage 变成 Server RPC + OnHealthChanged 广播加 Replicated 回调。多数架构改动集中在 C++ 层,蓝图表现层几乎不用动——这就是分层带来的可维护性。
本章小结
- 实战架构原则:规则在 C++、表现走接口与广播、UI 只订阅不决策。
- 角色↔武器↔敌人↔UI 四段通信,分别对应组合/接口/广播三种手段。
- 分层做好后,网络化等大改动集中在 C++ 层,蓝图层稳定不动。
