当前位置: 首页 > ai >正文

UE源代码——径向爆炸伤害计算函数(Grenade手雷爆炸功能)

        当我们想设计实现一个爆炸功能时,应该怎么办? 如何考虑服务端与客户端优先权的问题?如何设计出一个合理的功能。

UE源代码中给我们提供了一个相当细节爆炸实现函数,里面写了详细的注释。应该如何使用这个函数,注意事项.

声明与解释:

代码前导声明标记,可以在什么地方使用。 UE 中的meta 为自定义类型,意思就是怎么实现看你自己,提供更广阔的施展空间(具体可以看看UE中meta的用法)。所以这个函数,是UE 手动自己造的一个。

UFUNCTION(BlueprintCallable,                // 可在蓝图中调用BlueprintAuthorityOnly,           // 仅在拥有网络权限的服务器上执行Category="Game|Damage",           // 在蓝图中的分类路径meta=(WorldContext="WorldContextObject",  // 指定世界上下文参数AutoCreateRefTerm="IgnoreActors"    // 自动创建引用参数)
)
1. BlueprintCallable
  • 作用:允许在蓝图图表中调用此函数
  • 效果:
    • 函数会出现在蓝图的 "调用函数" 节点列表中
    • 可通过蓝图可视化编程直接调用 C++ 逻辑
  • 适用场景:需要在蓝图中实现的核心游戏逻辑(如伤害计算)
2. BlueprintAuthorityOnly
  • 作用:确保函数仅在拥有网络权限的服务器上执行
  • 网络逻辑:
    • 客户端调用此函数时,实际执行会转发到服务器
    • 防止客户端作弊修改伤害计算逻辑
  • 注意事项:
    • 函数执行结果需要通过网络同步回客户端
    • 纯单机游戏中此参数无效
3. Category="Game|Damage"
  • 作用:在蓝图编辑器中对函数进行分类
  • 显示效果:
    • 函数会出现在蓝图节点面板的 "Game → Damage" 类别下
    • 多层级分类使用竖线 (|) 分隔
  • 最佳实践:
    • 按功能模块组织函数(如 "Gameplay/Combat"、"UI/Navigation")
    • 保持分类结构简洁清晰
4. meta 参数详解
WorldContext="WorldContextObject"
  • 作用:指定哪个参数是用于获取游戏世界的上下文对象
  • 技术实现:
    • 虚幻引擎通过该参数获取 UWorld 实例
    • 确保函数在正确的游戏世界上下文中执行
  • 对应代码参数:

    cpp

    const UObject* WorldContextObject
    
AutoCreateRefTerm="IgnoreActors"
  • 作用:自动为引用参数创建可修改的输入项
  • 参数要求:
    • 针对类型为TArray<AActor*>&的引用参数
    • 允许在蓝图中动态修改传入的 Actor 数组
  • 蓝图表现:
    • 在蓝图节点中会显示为可编辑的数组输入框

函数在蓝图中的使用示例

当这个 C++ 函数被正确暴露后,在蓝图中可以这样使用:

  1. 在蓝图图表中添加 "调用函数" 节点
  2. 在 "Game|Damage" 类别下找到此函数
  3. 连接各输入参数:
    • WorldContextObject:通常连接 "Self" 引用
    • BaseDamage/MinimumDamage:设置数值
    • Origin:连接位置向量(如技能释放点)
    • IgnoreActors:添加需要忽略的 Actor 列表
  4. 处理返回值(是否成功应用伤害)

与网络同步相关的注意事项

由于标记了BlueprintAuthorityOnly,此函数的网络执行流程为:

  1. 客户端蓝图调用此函数
  2. 请求通过网络发送到服务器
  3. 服务器执行实际的伤害计算逻辑
  4. 服务器通过网络通知客户端伤害结果
  5. 客户端播放伤害反馈效果(如特效、音效)

这种设计确保了多人游戏中伤害计算的一致性和安全性。

源代码:  所有细节

关键参数说明

  • BaseDamage:中心点的最大伤害值。
  • MinimumDamage:范围外边界的最小伤害值。
  • Origin:伤害范围的球心位置。
  • DamageInnerRadius:伤害保持最大值的内半径。
  • DamageOuterRadius:伤害衰减的外半径。
  • DamageFalloff:伤害衰减曲线控制参数(指数衰减)。
  • IgnoreActors:忽略的伤害目标列表。

实现流程

  1. 碰撞检测初始化 使用 FCollisionQueryParams 配置碰撞检测参数,包括忽略特定 Actor
TArray<FOverlapResult> Overlaps;
World->OverlapMultiByObjectType(Overlaps, Origin, FQuat::Identity, FCollisionObjectQueryParams::InitType::AllDynamicObjects, FCollisionShape::MakeSphere(DamageOuterRadius), SphereParams);

      2.球形范围检测 通过 OverlapMultiByObjectType 检测范围内所有动态对象:

TArray<FOverlapResult> Overlaps;
World->OverlapMultiByObjectType(Overlaps, Origin, FQuat::Identity, FCollisionObjectQueryParams::InitType::AllDynamicObjects, FCollisionShape::MakeSphere(DamageOuterRadius), SphereParams);

      3. 筛选可伤害目标 遍历检测结果,过滤不可伤害或需忽略的 Actor:

if (OverlapActor && OverlapActor->CanBeDamaged() && OverlapActor != DamageCauser && Overlap.Component.IsValid())

 

       4. 伤害事件构造 创建 FRadialDamageEvent 并配置伤害参数(包括衰减参数):

FRadialDamageEvent DmgEvent;
DmgEvent.Params = FRadialDamageParams(BaseDamage, MinimumDamage, DamageInnerRadius, DamageOuterRadius, DamageFalloff);

 

        5.应用伤害 对每个有效目标调用 TakeDamage 方法:

TakeDamage 需要我们重载自定义的重新实现一下。因为这里重新实现了,伤害的计算方式。

Victim->TakeDamage(BaseDamage, DmgEvent, InstigatedByController, DamageCauser);

所以,一个完整的,带有衰减,距离检测,持续时间,爆炸范围的函数应该怎么用呢? 如下,

拿过来,只需要我们调用ApplyRadialDamageWithFalloff 此函数,并填好对应的参数就可以了

TArray<AActor*> IgnoredActors;
UGameplayStatics::ApplyRadialDamageWithFalloff(GetWorld(), 50.0f,  // BaseDamage10.0f,  // MinimumDamageExplosionLocation, 300.0f, // InnerRadius600.0f, // OuterRadius2.0f,   // FalloffUDamageType::StaticClass(), IgnoredActors,this,   // DamageCausernullptr // InstigatedByController
);
 

http://www.xdnf.cn/news/9157.html

相关文章:

  • C++ 中的函数包装:std::bind()、std::function<>、函数指针与 Lambda
  • ComfyUI 文生图,绘图要求中 正向提示词、负向提示词 有什么区别,webp又是什么格式 comfyui 那么喜欢它
  • 冯 • 诺依曼体系结构
  • 在 Unity 中,Start 方法直接设置 RectTransform 的位置,时出现问题,与预计位置不匹配。
  • Vue 3.0 中provide常见使用场景
  • 一个开源的多播放源自动采集在线影视网站
  • GitCode镜像仓库批量下载开发实录
  • 【Redis】过期键删除策略,LRU和LFU在redis中的实现,缓存与数据库双写一致性问题,go案例
  • 第12次08: 省市县区三级联动收货地址
  • 沉石鱼惊旋
  • CVE-2021-44228源码分析与漏洞复现
  • Redis学习打卡-Day7-高可用(下)
  • 学习心得(19)如何验证Form表单里的数据是对的?
  • 并发基础|进程与线程
  • 使用NSIS 和 VNISEdit 打包 electron 程序为 exe 向导式安装包
  • 制药行业数字化转型:从挑战到智能化落地的实践路径
  • 嵌入式学习Day28
  • FreeRTOS——事件标志组
  • Java 权威方案:彻底修复 OPTIONS 方法安全漏洞(附企业级案例与测试指南)
  • 今日行情明日机会——20250526
  • 固态硬盘不识别或掉盘如何解决?——以Kingston FURY Renegade G5为例
  • Qwen-Agent的使用示例-天气查询(function calling)
  • 电子电路原理第十七章(线性运算放大器电路的应用)
  • 【登录优化】redis删除旧token
  • AI测试进入智能体时代:AutoGen 、 Coze、CrewAI 谁主沉浮?
  • C++ STL map multimap 查找操作详解
  • 2025-5-26Vue3快速上手
  • Nginx location匹配模式详解
  • 解锁 MCP 中的 JSON-RPC:跨平台通信的奥秘
  • nfs下载镜像报错File lookup fail,TTTTTTTTTTTTTTT,内核 6.11.0降到5.15.0