关于 godot-combat-system
godot-combat-system 是面向 Godot 开发者的战斗系统技能,涵盖伤害、生命值、命中框和常见战斗模式。它以类型化 DamageData 和组件化实践为核心,帮助避免常见战斗逻辑问题。
主要功能
- 01类型化 DamageData 资源与伤害标志
- 02支持伤害和无敌帧的 HealthComponent
- 03命中框与受击框连接方式
- 04范围伤害、硬直与鸭子类型模式
- 05可选连击、遥测和调试脚本
适用场景
- 01实现包含抗性和暴击信息的类型化伤害
- 02构建近战或投射物命中窗口
- 03无需临时 Area 节点实现范围攻击
- 04检查战斗事件或验证网络伤害
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ thedivergentai/ game-dev-agentic-skills --skill godot-combat-system安装后在 Claude Code 中输入/godot-combat-system确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/elite-combat-patterns.mdmigration-notes.mdscripts/combat_logger.gdcombat_state.gdcombat_system_patterns.gdcombo_system.gddamage_data.gddamage_popup.gdhealth_component.gdhitbox_component.gdhitbox_hurtbox.gdhitbox_visualizer.gdnetworked_damage_manager.gd详细介绍
绝对不要做
- 绝对不要直接引用伤害(
target.health -= 10)——这会绕过护甲、抗性和无敌帧。始终使用DamageData+HealthComponent.take_damage。 - 绝对不要忘记无敌帧(i-frames)——否则多段命中形状会在每个物理帧都触发。成功命中后,务必应用一个短暂的无敌窗口。
- 绝对不要让命中框永久处于激活状态——使用 AnimationPlayer 轨道或定时代码启用/禁用;永久监测会导致幽灵命中。
- 绝对不要使用分组筛选基于物理的命中——优先使用碰撞层/掩码(C++ 筛选器)。分组用于次要逻辑,而不是物理门控。
- 绝对不要在没有 DamageData 对象的情况下发出伤害信号——原始数值会丢失类型、来源、击退和暴击上下文。
- 绝对不要使用原始字符串表示元素伤害类型——使用
enum/@export_flags位字段。字符串"physical"违反了此技能自身的约定。 - 绝对不要用 try/catch 验证目标——GDScript 没有异常。使用
has_method(&"take_damage")/is检查。 - 绝对不要使用
OS.delay_msec()硬编码受击硬直——这会阻塞 OS 线程。使用补间 /Engine.time_scale+ignore_time_scale定时器。 - 绝对不要在
_process()中应用 RigidBody 冲量——使用_physics_process/_integrate_forces。 - 绝对不要在 Player 脚本中耦合 UI 生命条——发出
health_changed信号;由 HUD 监听。 - 绝对不要让已死亡实体上的 CollisionShapes 保持激活——死亡时调用
set_deferred("disabled", true)。 - 绝对不要对 CollisionShapes 使用非等比缩放——缩放形状资源(
radius、size),而不是不均匀地缩放节点变换。 - 绝对不要使用实例化的 Nodes 存储基础战斗属性——优先使用
Resource/RefCounted容器;每个实例都调用duplicate()。 - 绝对不要在高频状态名称中使用普通字符串——优先使用
StringName(&"attacking")。 - 绝对不要忘记对共享的 Resource 属性调用
duplicate()——共享模板 = 共享生命值池。
黄金路径(强制)
- damage_data.gd — 带有伤害类型
enum/ 标志位的类型化DamageDataResource(不含 String 元素)。 - health_component.gd —
take_damage+ 无敌帧门控 +health_changed/died信号。 - hitbox_hurtbox.gd / hitbox_component.gd — Area 将命中传递给受击框。
- combat_system_patterns.gd — 鸭子类型、受击停顿、无节点 AoE、帧同步。
不要在场景中重新内联 Hitbox/Health/Combo/Ability 教程。将能力路由到 godot-ability-system;按照 godot-composition 组合组件;通过 godot-state-machine-advanced 实现 FSM。
决策树
| 任务 | 加载 | 不要加载 |
|---|---|---|
| 定义伤害载荷 | damage_data.gd | String damage_type 字段 |
| HP + 无敌帧 | health_component.gd | 直接使用 health -= n |
| 近战/投射物体积 | hitbox_hurtbox.gd / hitbox_component.gd | 永久监测的 Areas |
| AoE / 受击停顿 / 鸭子类型 | combat_system_patterns.gd | 每个 tick 都生成临时 Areas |
| 能力冷却 / 技能栏 | godot-ability-system | 在此处内联冗长的 AbilityManager 教程 |
| 连击缓冲 | godot-input-handling + 状态机 | 在 _input 中嵌入命中逻辑 |
伤害类型约定(与“绝对不要做”保持一致)
# From damage_data.gd — prefer this shape everywhere
enum DamageType { PHYSICAL = 1, FIRE = 2, ICE = 4, LIGHTNING = 8, POISON = 16 }
@export_flags("Physical", "Fire", "Ice", "Lightning", "Poison")
var damage_types: int = DamageType.PHYSICAL
命中框必须传递 DamageData(或使用相同标志位构建的等效 AttackData),绝不能传递 "Physical" 字符串。
可用脚本
- damage_data.gd — 必需 DamageData 资源 + 类型标记。
- health_component.gd — 必需 Health + 无敌帧的标准实现路径。
- hitbox_hurtbox.gd — 必需,在接入 Area 战斗前使用。
- hitbox_component.gd — 与标记对齐的 3D Area hitbox 配套组件。
- combat_system_patterns.gd — 必需,用于 AoE / hit-stop / 鸭子类型。
- combo_system.gd — 带窗口的连击缓冲(没有连击时不要加载)。
- combat_state.gd — 轻量级战斗 FSM 门控。
- damage_popup.gd — 浮动伤害标签补间(生产环境中应使用对象池)。
- combat_logger.gd — 批量战斗遥测 JSON。
- networked_damage_manager.gd — 服务端验证伤害 RPC 框架。
- hitbox_visualizer.gd — 切换碰撞调试颜色。
精英级增量改进(保持简短)
- 战斗遥测: 通过 combat_logger.gd 批量刷新 JSON。
- 权威伤害判定: networked_damage_manager.gd — 客户端发起请求;服务端进行验证。
- Hitbox 调试: hitbox_visualizer.gd +
SceneTree.debug_collisions_hint。 - 连击 / 弹窗 / FSM: combo_system.gd、damage_popup.gd、combat_state.gd。
遥测、网络命中、连击以及移出的内嵌教程均必需:elite-combat-patterns.md。首次实现 DamageData + HealthComponent 时不要加载。
参考
渐进式披露: 仅查阅你要实现的 API 对应的官方文档(Areas、层/遮罩、Resources、信号、计时器、动画命中窗口)。接入相邻系统时再打开相关技能——不要预先加载整个技能网络。
官方文档
- 使用 Area2D — Hitbox/hurtbox 战斗使用 Area 重叠检测(
area_entered/ monitoring),而非 CharacterBody 移动查询。 - 物理学简介 — 命中筛选优先使用碰撞层/遮罩;分组速度较慢,不能替代高频战斗中的物理遮罩。
- Area2D — 2D 命中体积:用于队伍/阵营筛选的
monitoring/monitorable、area_entered和层/遮罩位。 - Area3D — 3D
HitboxComponent/ hurtbox 体积使用相同的 Area 重叠模型,并采用 3D 层和形状。 - CollisionShape2D — 使用
set_deferred("disabled", …)启用/禁用攻击形状,避免在物理步进期间修改物理服务器;切勿对节点进行非均匀缩放。 - PhysicsShapeQueryParameters3D — 使用
PhysicsDirectSpaceState3D上的intersect_shape实现无需生成临时 Area 节点的无节点 AoE/爆炸效果。 - AnimationPlayer — 通过动画轨道(或方法调用)控制 hitbox 的生效时段,避免攻击持续监测。
- 资源 — 将
DamageData/ 战斗属性作为数据(Resource/RefCounted)保存;为每个实例duplicate()共享模板,避免敌人共用一个生命值池。 - 使用信号 — 发出
health_changed/died/ 伤害事件,让 HUD 和 VFX 通过订阅接收信息,而不将生命条逻辑耦合到玩家脚本中。 - SceneTreeTimer — 在
Engine.time_scale = 0后进行受击停顿,必须使用create_timer(..., ignore_time_scale=true),否则解冻计时器会随世界一起冻结。 - Tween — 可中断的受击硬直/闪光 VFX:连续受击时,应终止并重新创建 tween,而不是叠加并行闪光动画。
- 高级多人游戏 — 权威伤害处理:客户端请求命中;服务器通过
@rpc验证并确认后,再应用take_damage。
相关技能
前置条件
- godot-2d-physics — Area 层/遮罩、延迟禁用
CollisionShape2D和空间查询,是 hitbox/hurtbox 筛选所依赖的物理基础。 - godot-signal-architecture — 伤害、生命值和死亡信号需要明确归属,确保战斗组件与 UI 和 AI 监听器保持解耦。
- godot-composition — 优先使用
HealthComponent/HitboxComponent子节点,而不是把战斗逻辑塞进单体 Character 脚本。 - godot-resource-data-patterns —
DamageData、元素标记和战斗属性应存放在 Resource/RefCounted数据中,并在生成时安全地调用duplicate()。
配套内容
- godot-ability-system — 技能会进入本技能的伤害/目标选择流水线;请将技能元数据与
DamageData分开存放。 - godot-rpg-stats — 护甲、抗性、暴击几率和修正器叠加会在写入生命值前馈入
take_damage。 - godot-animation-player — 攻击动画负责连招的判定框启用窗口、取消帧和恢复锁定。
- godot-state-machine-advanced — IDLE/ATTACKING/BLOCKING/STUNNED 战斗状态应属于负责控制
can_act的角色 FSM,而不是杂乱的临时布尔变量。 - godot-input-handling — 连招缓冲和攻击动作应通过动作映射调用战斗/连招系统,而不是在输入回调中嵌入命中逻辑。
下游/使用方
- godot-monte-carlo-balancer — 在
DamageData、无敌帧、冷却时间和暴击曲线都可调后,通过蒙特卡洛模拟验证 DPS/TTK 区间,再发布难度设置。 - godot-multiplayer-networking — 命中预测、延迟补偿和权限检查基于
DamageData与服务端验证 RPC 的拆分方案构建。 - godot-genre-action-rpg — 动作 RPG 战斗循环基于本技能,组合判定框、技能、属性和成长系统等类型特有的衔接逻辑。
主入口
- godot-master — 库路由器和镜像模块入口;发现相关技能或在编辑 Domain Skill 后同步共享脚本镜像时使用。
评论
支持 Markdown