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++ 实现

函数参数与你蓝图原接口完全对齐:伤害来源、伤害值、推力

  1. 敌人类实现层(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++

  1. 玩家侧调用层(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)
相关推荐
努力学习的小廉2 天前
UE5 入门系列(三):核心框架类全解析
ue5
平行云3 天前
建筑BIM/3D可视化轻量级实时评审与分享方案
unity·ue5·3dsmax·实时云渲染·云桌面·云游戏·建筑bim
BugPhysician8 天前
影之刃零首发UE崩溃排查:着色器缓存、虚拟内存与驱动版本
ue5·影之刃零·影之刃零报错·影之刃零进不去·ue崩溃·ue引擎崩溃·ue5引擎崩溃
电子云与长程纠缠9 天前
UE5魂系游戏开发教程05
开发语言·学习·游戏·ui·ue5
fanfan_hongyun9 天前
UE5.1 蓝图调用C++方法
ue5
易知微EasyV数据可视化9 天前
UE5 中接入 GDAL:从vcpkg编译到插件打包
ue5
努力学习的小廉9 天前
UE5入门系列(一):环境搭建.md
ue5
fanfan_hongyun10 天前
【UE5.1 创建C++文件】
c++·ue5
努力学习的小廉10 天前
UE5 入门系列(二):编辑器基础操作速通
ue5·编辑器
Дерек的学习记录10 天前
Unreal Engine 5:开关门实现和流程控制
开发语言·学习·ue5