用 Godot 4 拆解 MOBA 技能:前摇、判定、后摇与冷却如何做成可靠状态机

用 Godot 4 拆解 MOBA 技能:前摇、判定、后摇与冷却如何做成可靠状态机

OK,OK,大家好,欢迎大家来到大鹏 AI 教育,我是张大鹏。

做 MOBA 原型时,很多人会把技能写成"按下 Q,立刻冲刺并造成伤害"。演示能跑,但只要加入动画、打断、网络同步或连续输入,逻辑很快就会互相打架。

这篇文章借鉴《英雄联盟》技能的节奏感,但不复刻任何英雄或资源。我们只提炼一个通用工程问题:如何在 Godot 4 中把一次技能拆成前摇、激活、后摇和冷却,并让每个阶段都可观察、可测试、可打断。

为什么技能不能只是一个函数

一次完整技能至少包含四段时间:

  • 前摇(wind-up):播放起手动作,通常允许转向,但未必允许移动。
  • 激活(active):位移、投射物或伤害判定真正生效。
  • 后摇(recovery):收招阶段,限制下一次动作,维持手感和可读性。
  • 冷却(cooldown):角色可以继续行动,但该技能暂时不可再次使用。

如果把四段全部塞进一个函数和若干 await,取消技能时很容易留下未清理的碰撞区、特效或速度。状态机的价值不是"代码看起来高级",而是让任意时刻只有一种明确解释。

先把输入从技能逻辑中分离

在 Input Map 中创建 skill_primary,再把 Q 键、手柄按键等输入绑定到这个动作。脚本只读取"主要技能"这个意图,不关心物理按键。

gdscript 复制代码
func _unhandled_input(event: InputEvent) -> void:
    if event.is_action_pressed("skill_primary"):
        skill_machine.request_cast()

输入层只发出请求,能否释放由状态机判断。这样 UI 点击、AI 控制或网络指令也能复用同一个入口。

用枚举表达技能生命周期

gdscript 复制代码
class_name DashSkill
extends Node

enum Phase { READY, WIND_UP, ACTIVE, RECOVERY, COOLDOWN }

@export var wind_up := 0.18
@export var active_time := 0.12
@export var recovery := 0.25
@export var cooldown := 4.0
@export var dash_speed := 720.0

var phase: Phase = Phase.READY
var phase_left := 0.0
var cast_direction := Vector2.RIGHT

signal phase_changed(next_phase: Phase)
signal hit_window_changed(enabled: bool)

四个持续时间都使用导出变量,让策划能在 Inspector 中调节。phase_changed 给动画、音效和 UI 使用;技能核心不需要直接操作所有表现节点。

请求释放时锁定关键数据

gdscript 复制代码
func request_cast() -> bool:
    if phase != Phase.READY:
        return false

    cast_direction = owner.facing_direction.normalized()
    _enter_phase(Phase.WIND_UP, wind_up)
    return true

方向要在释放时锁定,还是在前摇结束时重新读取,取决于设计。两种都合理,但必须明确。竞技技能最怕"代码偶尔读取当前方向",导致同样输入出现不同结果。

在物理帧推进状态

位移和命中窗口应跟随 _physics_process(),避免渲染帧率改变技能距离。

gdscript 复制代码
func _physics_process(delta: float) -> void:
    if phase == Phase.READY:
        return

    phase_left -= delta

    if phase == Phase.ACTIVE:
        owner.velocity = cast_direction * dash_speed
        owner.move_and_slide()

    if phase_left <= 0.0:
        _advance_phase()
gdscript 复制代码
func _advance_phase() -> void:
    match phase:
        Phase.WIND_UP:
            _enter_phase(Phase.ACTIVE, active_time)
            hit_window_changed.emit(true)
        Phase.ACTIVE:
            hit_window_changed.emit(false)
            owner.velocity = Vector2.ZERO
            _enter_phase(Phase.RECOVERY, recovery)
        Phase.RECOVERY:
            _enter_phase(Phase.COOLDOWN, cooldown)
        Phase.COOLDOWN:
            _enter_phase(Phase.READY, 0.0)

func _enter_phase(next: Phase, duration: float) -> void:
    phase = next
    phase_left = duration
    phase_changed.emit(next)

伤害区只在 ACTIVE 阶段开启。即使动画比判定更长,也不应该让整段动画都能造成伤害。

打断不是直接改回 READY

眩晕、死亡或场景切换都会打断技能。取消函数必须清理所有副作用:

gdscript 复制代码
func cancel() -> void:
    hit_window_changed.emit(false)
    owner.velocity = Vector2.ZERO
    _enter_phase(Phase.READY, 0.0)

实际项目还应在这里停止循环音效、回收特效、解除霸体标记。一个很好用的规则是:凡是在进入阶段时打开的东西,都要在退出或取消时关闭。

用 Timer 还是 delta

两种方案都能工作:

  • 阶段很多、需要暂停与精确调试时,用一个状态机统一递减 delta 更直观。
  • 独立的一次性事件适合 Timertimeout 信号。
  • 不要同时让 Timer、动画回调和 _physics_process() 争夺同一状态的控制权。

冷却 UI 可以订阅状态信号,再读取 phase_left / cooldown,而不是反过来由 UI 决定技能是否可用。

验收清单

  • 连续狂按技能键只会成功释放一次。
  • 前摇期间没有提前打开伤害区。
  • 激活时间改变后,位移距离仍等于 dash_speed × active_time 的预期结果。
  • 技能被打断后,碰撞区、速度、音效和特效都被清理。
  • 冷却结束只发生一次,并稳定回到 READY
  • 低帧率与高帧率下,技能距离和命中时机基本一致。

小结

MOBA 技能的手感首先来自清楚的时间结构。把输入请求、阶段推进、物理位移、伤害窗口和表现信号拆开后,动画取消、连招、AI 施法和网络同步才有可靠的落点。

这套结构下一步可以继续扩展"可取消窗口"和"输入缓冲",让后摇并非绝对锁死,而是能在指定帧衔接下一招。

参考资料

  • 《大鹏 Godot 4 游戏开发入门》第 4 章:_physics_process()、Input Map、信号与 Timer
  • AiGameLOL:官方英雄技能数据仅用于私有研究与结构分析;本文未复用官方美术或技能文案
  • Godot 官方文档:Input、Timer、CharacterBody2D
相关推荐
Python私教1 小时前
Blender + Godot 4 制作 MOBA 防御塔:从低模、GLB 到碰撞与攻击范围
godot
Python私教3 天前
Godot 4 角色移动为什么要用 CharacterBody2D?从 Input Map 到碰撞滑动一次讲透
godot
Python私教3 天前
Godot 4 TileMapLayer 入门:从图集、碰撞到可玩的 2D 关卡
godot
Python私教3 天前
Godot图片怎么导入?PNG、压缩、Mipmap与Reimport一次讲清
游戏引擎·godot
Python私教3 天前
Blender模型导入Godot完整教程:GLB、BLEND与继承场景怎么选
运维·godot·blender
寒水馨3 天前
Linux下载、安装godot-4.7.1-stable(附安装包Godot_v4.7.1-stable_linux.x86_64.zip)
linux·游戏引擎·godot·游戏开发·2d游戏·3d游戏·godot engine
寒水馨3 天前
macOS下载、安装godot-4.7.1-stable(附安装包Godot_v4.7.1-stable_macos.universal.zip)
macos·3d·游戏引擎·godot·跨平台·游戏开发·2d