# GDStateFlow **Repository Path**: MeDeity/GDStateFlow ## Basic Information - **Project Name**: GDStateFlow - **Description**: 一个为 Godot 4.x 设计的轻量级扁平状态机库。零依赖,两个脚本,复制即用。 - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-06-26 - **Last Updated**: 2026-06-26 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # GDStateFlow 一个为 Godot 4.x 设计的轻量级扁平状态机库。零依赖,两个脚本,复制即用。 > **加状态 = 新建一个文件。** 就这样。 --- ## 为什么需要这个? 传统的 `enum + match` 方案一开始没问题,但状态多了以后—— - 一个文件几百行,所有状态逻辑糊在一起 - 加一个状态要改 enum、加 match 分支、找插入位置 - 想把"待机状态"复用到另一个角色?复制粘贴,改半天 GDStateFlow 换了一种思路:每个状态都是一个独立的 GDScript 文件,继承自统一的 `State` 基类。`StateMachine` 节点负责转换、生命周期和历史记录 —— 你的状态文件只管这个状态自己的逻辑。 --- ## 项目结构 ``` GDStateFlow/ ├── state_machine.gd # StateMachine 节点(挂到你的场景上) ├── state.gd # State 基类(状态脚本继承它) ├── icon.svg ├── LICENSE # MIT 协议 ├── project.godot └── examples/ └── platformer/ ├── PlatformerDemo.tscn ├── player.gd └── states/ ├── idle_state.gd ├── walk_state.gd └── jump_state.gd ``` --- ## 快速上手 ### 1. 添加到项目 把 `state_machine.gd` 和 `state.gd` 复制到你的项目里。就这两个文件,够了。 ### 2. 搭建场景树 ``` Player (CharacterBody2D) ├── StateMachine (Node) ← 挂上 state_machine.gd ├── CollisionShape2D └── Sprite2D ``` ### 3. 创建状态 每个状态都是一个独立脚本,继承 `State`: ```gdscript # states/idle_state.gd extends State func enter(target: Node) -> void: target.velocity = Vector2.ZERO func process_state(delta: float, target: Node) -> void: if Input.is_action_just_pressed("ui_left"): transition_to(preload("res://states/walk_state.gd")) ``` ### 4. 从玩家脚本初始化 ```gdscript # player.gd extends CharacterBody2D @onready var state_machine: StateMachine = $StateMachine func _ready() -> void: state_machine.transition_to(preload("res://states/idle_state.gd")) ``` --- ## API 参考 ### `StateMachine`(继承 `Node`) #### 属性 | 属性 | 类型 | 说明 | |------|------|------| | `debug` | `bool` | 设为 `true` 时会在控制台打印状态转换信息。默认:`false` | | `target` | `Node` | 被状态机控制的节点。默认取 `get_parent()` | | `current_state` | `GDScript` | 当前活跃的状态脚本 | | `previous_state` | `GDScript` | 上一个状态脚本(供 `transition_back()` 使用) | #### 方法 | 方法 | 说明 | |------|------| | `register_transitions(rules: Dictionary)` | 注册允许的状态转换规则。格式:`{ 状态脚本: [允许的状态A, 允许的状态B] }` | | `transition_to(new_state: GDScript)` | 转换到新状态。先调用旧状态的 `exit()`,再调用新状态的 `enter(target)`。 | | `transition_back()` | 回退到上一个状态。 | #### 生命周期 每个物理帧,状态机自动在活跃状态实例上调用 `process_state(delta, target)`。 --- ### `State`(继承 `Node`) #### 在你的状态脚本中覆写这些方法 | 方法 | 说明 | |------|------| | `enter(target: Node)` | 进入该状态时调用。 | | `exit(target: Node)` | 离开该状态时调用。 | | `process_state(delta: float, target: Node)` | 该状态活跃时每个物理帧调用。 | #### 在状态内部调用 | 方法 | 说明 | |------|------| | `transition_to(new_state: GDScript)` | 便捷方法 —— 通过父级 `StateMachine` 触发状态转换。 | --- ## 功能特性 ### 转换规则校验 通过注册允许的转换来防止非法状态跳转: ```gdscript state_machine.register_transitions({ preload("states/idle_state.gd"): [ preload("states/walk_state.gd"), preload("states/jump_state.gd"), ], preload("states/jump_state.gd"): [ preload("states/idle_state.gd"), # 跳跃中只能落地到待机 ], }) ``` 非法转换会直接报错,不会默默失败。 ### 状态历史回退(transition_back) 内置返回上一状态的支持: ```gdscript func take_damage() -> void: state_machine.transition_to(preload("states/hurt_state.gd")) func on_hurt_finished() -> void: state_machine.transition_back() # 自动回到受伤前的状态 ``` ### 调试模式 在 Inspector 里把 `debug = true`,就能看到所有状态流转日志: ``` [StateMachine] → idle_state [StateMachine] idle_state → walk_state [StateMachine] walk_state → idle_state ``` 关掉就是零开销。 ### target 解耦 状态里不写 `get_parent()`,写的是 `target`。同一个状态脚本可以给玩家用、给敌人用、给 UI 用 —— 完全复用。 --- ## 示例 `examples/platformer/` 目录包含一个完整的可运行演示: - **IdleState** —— 等待输入,可转换到行走或跳跃 - **WalkState** —— 水平移动,使用 `move_and_slide()` - **JumpState** —— 应用重力,落地时回到待机状态 运行 `PlatformerDemo.tscn` 就能看到效果。StateMachine 节点开了 `debug = true`,你可以在控制台观察状态转换。 --- ## 和其他方案对比 | 方案 | 优点 | 缺点 | |------|------|------| | **enum + match** | 零学习成本 | 一个文件几百行,状态一多就不可维护 | | **Node 子节点方案**(GDQuest 风格) | 编辑器可视化 | 10 个状态 = 11 个节点,太重 | | **Resource 配置方案** | 数据驱动 | 学习曲线陡 | | **GDStateFlow** | 一个文件一个状态,轻量 | 无可视化编辑 | **适用场景:** 角色状态机、UI 状态机、敌人 AI,尤其是状态数在 3-10 个的项目。 --- ## 环境要求 - Godot 4.x(基于 4.6 开发和测试) --- ## 赞赏 如果这个项目对你有帮助,欢迎请我喝杯☕。这让我能继续做这种小而美的工具。 微信赞赏码 --- ## 开源协议 MIT。随便用 —— 个人项目、商业游戏,都行。 --- ## 路线图 | 版本 | 计划 | |------|------| | v1.0 | 脚本库形式,复制粘贴即用 | | v1.1 | 3 个完整示例(平台跳跃 / 敌人 AI / UI) | | v2.0 | 编辑器插件,Inspector 可视化 | | v2.1 | Godot Asset Library 正式发布 |