26,怪物受击接口改为C++

📅 2026/7/22 3:18:54 👁️ 阅读次数 📝 编程学习
26,怪物受击接口改为C++

整条链路如下:

一、核心设计目标
实现玩家攻击 → 敌人受击的完整链路
接口与业务逻辑分离,蓝图 / C++ 双向兼容
变量全私有,仅通过Set/Get访问,数据安全可控
死亡判断前置过滤,性能与逻辑双保障
二、分层架构与实现细节

  1. 接口层(HitHandle_enemy.h)
    作用:定义统一受击协议,不包含任何业务逻辑
    cpp
    运行
    UINTERFACE(MinimalAPI)
    class UHitHandle_enemy : public UInterface
    { GENERATED_BODY() };

class ROUGHLIKE1_API IHitHandle_enemy
{
GENERATED_BODY()
public:
UFUNCTION(BlueprintNativeEvent, Category = “Hit”)
void INT_HitHandleEnemy(AActor* DamageCauser, float Damage, float Force);
virtual void INT_HitHandleEnemy_Implementation(AActor* DamageCauser, float Damage, float Force) = 0;
};
采用BlueprintNativeEvent,支持蓝图重写与 C++ 实现
函数参数与你蓝图原接口完全对齐:伤害来源、伤害值、推力
2. 敌人类实现层(Enemy.h/.cpp)
2.1 类继承与接口绑定
cpp
运行
// Enemy.h
UCLASS()
class ROUGHLIKE1_API AEnemy
: public APaperZDCharacter
, public IHitHandle_enemy
{
GENERATED_BODY()
public:
// 接口实现声明
virtual void INT_HitHandleEnemy_Implementation(AActor* DamageCauser, float Damage, float Force) override;

// 通用受击入口(蓝图/C++均可调用) UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "Combat | Attack") void OnTakeHit(AActor* DamageCauser, float Damage, float Force); virtual void OnTakeHit_Implementation(AActor* DamageCauser, float Damage, float Force); // 全私有变量的Set/Get接口(HP、死亡状态、伤害数据等) // ...(完整实现见之前的代码)

};
2.2 核心转发逻辑(接口与通用入口解耦)
cpp
运行
// Enemy.cpp
// 接口仅做转发,不写业务逻辑
void AEnemy::INT_HitHandleEnemy_Implementation(AActor* DamageCauser, float Damage, float Force)
{
OnTakeHit(DamageCauser, Damage, Force);
}

// 通用受击入口,蓝图重写优先级高于C++默认实现
void AEnemy::OnTakeHit_Implementation(AActor* DamageCauser, float Damage, float Force)
{
// C++默认空实现,逻辑由蓝图编写
}
接口层仅转发,保留原有接口兼容性

OnTakeHit作为统一入口,支持蓝图调试与后续迁移 C++
3. 玩家侧调用层(MyPaperZDCharacter.cpp)
作用:攻击检测 + 伤害计算 + 接口调用,完全收进 C++
cpp
运行
void AMyPaperZDCharacter::INT_AttackDetection_Implementation(FVector boxPosition, FVector boxExtension)
{
// 1. 死亡前置过滤,直接阻断无效攻击
if (IsDead) return;

// 2. 盒体检测命中敌人 // ...(检测逻辑) // 3. 遍历敌人,统一分发伤害 for (AActor* target : outActors) { if (!target || !target->ActorHasTag(FName("enemy"))) continue; // 4. C++内完成暴击伤害计算(替代蓝图逻辑) bool bIsCrit = UKismetMathLibrary::RandomBoolWithWeight(AttackCritChance); float finalDamage = AttackBaseDamage * (bIsCrit ? AttackCritMultiplier : 1.0f); int32 truncatedForce = static_cast<int32>(force); // 5. 标准接口调用(必须用Execute_前缀) if (target->Implements<UHitHandle_enemy>()) { IHitHandle_enemy::Execute_INT_HitHandleEnemy( target, this, finalDamage, truncatedForce); } }

}

  1. 蓝图层实现(敌人蓝图)
    作用:仅实现受击业务逻辑,不写任何分发逻辑
    删除蓝图中原有的Event INT Hithandle节点,避免覆盖 C++ 转发
    保留Event On Take Hit事件,编写受击逻辑:
    调用SetDamageCauser/SetReceivedDamage/SetReceivedForce
    扣血SetHP(GetHP() - Damage)
    HP 归零时调用SetDead(true)