使用指南

实战教程 / 打砖块案例拆解

把完整打砖块示例拆成 PlayButton、Game、Player 三条工作流,说明真实项目如何组织节点。

16

一个完整案例最能看出来 Script Graph 的组织方式:不是把所有逻辑塞进一张巨图,而是按职责拆成几张小图,每张只做一件事

我们用打砖块这个经典玩法做例子——它足够小,能在一次教程里讲完;又足够真,能覆盖 UI、关卡生成、玩家控制三个真实项目里都会遇到的问题。

案例的三条工作流

工作流负责什么
PlayButton.sgw首页开始按钮:拿 Button 组件、绑定点击、切场景
Game.sgw关卡启动:加载资产、批量创建砖块、设置父节点
Player.sgw玩家控制:绑定键盘、判断方向、驱动 2D 物理

这样拆的核心是——UI 层、关卡层、玩家层各管各的,只通过明确定义的事件、变量或节点引用协作。这也是所有中大型可视化脚本项目的通用组织方式:任何一张图都不该”什么都懂一点”。

PlayButton:从 UI 进入游戏

PlayButton 只关心一件事——开始按钮。

启动事件
  → 获取 Button
  → 绑定点击事件
  → 切换到游戏场景

它不生成砖块、不控制玩家。这点很重要——按钮的图会永远保持简单,未来改 UI 皮肤时你不会碰到玩法逻辑,两个模块彼此隔离。

Game:负责关卡的初始化

Game 是关卡的编舞者:

启动事件
  → 加载资产包
  → 加载 Brick Prefab
  → 外层循环行
  → 内层循环列
  → 实例化砖块
  → 设置父节点和位置

这里会碰到几乎所有你会遇到的资产 + 循环 + 数学操作。做这一段时强烈建议一层一层地打印——先只打印外层循环的行索引,确认循环次数对了;再加内层循环的列索引;确认坐标算对了;最后再接实例化。

一个真实经验:大部分”砖块位置乱了/数量不对”的问题,其实都是循环变量或坐标公式写错了。这些问题在图里静态看是看不出来的,只有打印出来才能定位。

Player:负责玩家的输入和运动

Player 挂在玩家节点上:

启动事件
  → 绑定键盘事件
  → 根据按键更新移动方向
  → 枚举 Switch 判断方向
  → 操作 2D 刚体或节点位置

方向管理这里有个小陷阱:别用字符串 "left""right" 这种散落写法。定义一个 MoveDirection 枚举,让所有比较、Switch 分支都走枚举——枚举可以自动完成、可以在编译期检查,字符串不能。

这个建议看起来”多此一举”,但当你从 4 个方向扩展到 8 个方向、加上 Idle、加上 Dashing 时,枚举会救你一命。

从这个案例学到的组织原则

  • UI 事件和玩法初始化分离——一张图只做一件事。
  • 生成大量对象时,用循环 + 函数库减少重复节点——不要复制粘贴 20 个类似的节点。
  • 频繁一起传的一组数据,用结构体打包——比如”位置 + 旋转 + 尺寸”用一个 Transform 结构体。
  • 有限的状态和方向,用枚举管理——避免字符串散落各处。
  • 对象自己的行为放在自己身上——玩家控制在 Player.sgw、敌人 AI 在 EnemyAI.sgw,不要都塞进 GameManager。

排查顺序参考

真实项目里出问题时,按下面的顺序找:

现象先看哪里
开始按钮无效PlayButton 的点击事件是否有打印
场景切换成功但没砖块Game 的启动事件是否触发
砖块数量不对循环次数、行列索引、坐标计算
Prefab 没生成资产包名、资源路径、Prefab 类型
玩家不动键盘事件、方向枚举、刚体或节点引用
物理不生效2D 物理组件、碰撞体、刚体类型、场景是否启用 2D 物理

把这个案例当成模板

再复杂的项目,都可以按这个思路来组织:

  1. 先把系统列出来——UI、关卡、角色、敌人、道具、音效……
  2. 每个系统一个(或若干个)组件工作流或函数库。
  3. 每条工作流先接调试打印,跑通最短闭环,再接真实业务。
  4. 事件、变量、结构体、枚举建立系统之间的清晰边界,尽量少让两个系统直接持有对方的引用。

坚持这四步,你的项目在半年后依然会保持”打开一张图就能看懂”的状态——这是 Script Graph 最想让你养成的习惯。