关于 design-skill-progression-trees
面向游戏设计与开发者的技能和进度系统设计指南,采用有向无环图组织解锁路径。内容涵盖服务端验证、成本曲线、重置机制及节点效果建模。
主要功能
- 01以 DAG 建模前置条件
- 02服务端校验解锁请求
- 03设计渐进式成本曲线
- 04规划技能重置机制
- 05用 JSONB 存储效果数据
- 06检查循环与不可达节点
适用场景
- 01设计技能或天赋解锁图
- 02实现安全的玩家解锁接口
- 03规划重置费用与退款
- 04排查进度图的结构问题
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ fcsouza/ agent-skills --skill design-skill-progression-trees安装后在 Claude Code 中输入/design-skill-progression-trees确认已加载。
附带文件boilerplate/skill-tree.tstemplates/skill-tree-template.md
详细介绍
技能与成长树
用途
基于 DAG 的成长系统,适用于任何游戏类型——技能树、天赋树、能力解锁、被动属性图和声望层级。涵盖数据建模、服务端权威验证、成本缩放和重置机制。
适用场景
触发词:技能树、天赋树、能力树、成长系统、解锁系统、声望、节点图、技能点、能力解锁、被动树、天赋构筑、重置、技能重置
前置条件
game-design-fundamentals— 核心循环和奖励系统知识postgres-game-schema— 玩家和货币数据模型game-economy-design— 成本平衡和货币集成
核心原则
Chris Taylor(Supreme Commander):“优秀的科技树能让玩家感觉拥有无限选择,同时确保每条路线都切实可行。” Will Wright(The Sims、Spore):“当简单规则相互作用时,涌现系统便会出现——技能树应当相互组合,而非规定玩法。” Jonathan Blow(Braid、The Witness):“每次解锁都应让人感觉是一次真正的领悟,而不是勾选一个复选框。”
- DAG,而非树 — 前置条件应构成有向无环图;出现环路会破坏验证、回滚和一切相关功能。管理端写入时必须确保无环。
- 服务端权威解锁验证 — 绝不信任客户端的解锁请求。写入前,必须在服务端验证前置条件、货币和冷却时间。
- 保存前置条件快照以便回滚 — 在解锁时保存完整的前置条件状态。如果重置或补丁更改了图,就可以审计玩家解锁时哪些内容是有效的。
- 成本缩放遵循指数曲线 — 固定成本会导致终局节点相对于玩家收入而言过于便宜。使用
cost = baseCost * tier^exponent(指数通常为 1.5-2.0)。 - 重置应以玩家为先 — 始终提供重置机制,可以是带冷却时间的免费重置,也可以是付费的软货币重置。绝不让玩家永久受困于糟糕的选择。
- 效果是数据,而非代码 — 将效果存储为 JSONB(
{ "stat": "attack", "modifier": "+10%" })。在服务端应用。这样无需部署即可热重载、进行 A/B 测试和发布平衡补丁。 - 渐进式揭示 — 不要一次性显示所有节点。满足前置条件后再揭示节点。这样可以减轻玩家的压力,并创造探索惊喜(Jonathan Blow)。
分步说明
1. 定义节点类别
为每个节点分类:主动技能(玩家主动触发的能力)、被动属性(始终生效的加成)、解锁项(内容或机制的门槛)、声望(终局后重置获得的加成)。
2. 对 DAG 建模
使用存储在 JSONB 中的邻接表。每个节点都有一个包含节点 ID 的 prerequisites 数组。每次管理端写入时都要验证是否无环。
3. 编写 Drizzle Schema
创建 skill_nodes(成长树定义)和 player_skills(玩家状态)表。完整实现请参见样板代码。
4. 实现解锁 API
端点:POST /skills/unlock/:nodeId。流程:检查是否满足前置条件,检查货币是否充足,通过原子事务完成扣除货币、插入 player_skills 记录并保存快照。
5. 缓存已解锁节点
按玩家会话将已解锁的节点 ID 存储在 Redis 中。解锁或重置时使缓存失效。树查询十分频繁,逐个请求查询数据库太慢。
6. 添加重置端点
端点:POST /skills/respec。流程:扣除重置费用(或检查冷却时间),删除所有 player_skills 行,将技能点退还到玩家钱包,并使 Redis 缓存失效。
7. 添加成长树健康检查
仅限管理端使用的工具:环路检测(在前置条件图上执行 DFS)、孤立节点检测(前置条件引用了已删除节点的节点)、不可达节点检测。
Drizzle Schema
// skill_nodes — defines the tree structure (admin-managed)
export const skillNodes = pgTable("skill_nodes", {
id: text("id").primaryKey().$defaultFn(() => crypto.randomUUID()),
name: text("name").notNull(),
description: text("description"),
category: text("category").notNull(), // 'active' | 'passive' | 'unlock' | 'prestige'
tier: integer("tier").notNull().default(1),
prerequisites: jsonb("prerequisites").$type<string[]>().default([]),
cost: integer("cost").notNull().default(1),
effects: jsonb("effects").$type<Record<string, unknown>[]>().default([]),
isVisible: boolean("is_visible").notNull().default(true),
metadata: jsonb("metadata").$type<Record<string, unknown>>().default({}),
createdAt: timestamp("created_at").notNull().defaultNow(),
updatedAt: timestamp("updated_at").notNull().defaultNow(),
});
// player_skills — tracks which nodes each player has unlocked
export const playerSkills = pgTable("player_skills", {
id: text("id").primaryKey().$defaultFn(() => crypto.randomUUID()),
playerId: text("player_id").notNull().references(() => players.id, { onDelete: "cascade" }),
nodeId: text("node_id").notNull().references(() => skillNodes.id),
unlockedAt: timestamp("unlocked_at").notNull().defaultNow(),
snapshot: jsonb("snapshot").$type<Record<string, unknown>>().default({}),
});
API 模式
| 端点 | 方法 | 描述 |
|---|---|---|
/skills/tree | GET | 完整技能树,包含每个节点的玩家解锁状态 |
/skills/unlock/:nodeId | POST | 解锁节点——验证前置条件、扣除费用并执行原子写入 |
/skills/respec | POST | 完全重置——扣除费用、删除 player_skills 并返还点数 |
交叉引用
game-economy-design— 技能点的费用平衡与货币消耗机制postgres-game-schema— 玩家和货币表的架构redis-game-patterns— 按会话缓存已解锁节点集合game-design-fundamentals— 核心循环整合与成长节奏
陷阱与反模式
- “客户端技能树状态”——在客户端存储解锁状态;很容易被黑,必然导致不同步
- “没有重置机制”——做出错误选择的玩家会退出;务必提供重置途径
- “固定费用曲线”——每个节点费用相同;随着收入增长,后期节点会变得便宜得微不足道
- “缺少循环检测”——一个循环前置条件就会导致验证陷入无限循环;写入时务必确保是有向无环图(DAG)
- “效果硬编码”——将效果写死在代码中,而不是存储为 JSONB 数据;每次平衡性调整都需要部署
- “显示所有节点”——一开始就展示整棵技能树会让新玩家不知所措,还会破坏探索乐趣
设计理念
Chris Taylor(Supreme Commander、Total Annihilation):科技树应让玩家感受到自己正在构建强大的事物。每个分支都应让人觉得能开启新的战略可能性。如果玩家看到两个分支,其中一个明显更好,那么这棵树就设计失败了。
Will Wright(The Sims、SimCity、Spore):最好的成长系统,是通过简单规则之间的交互催生出涌现式构筑的系统。不要设计 50 种独特能力,而要设计 10 种可组合的能力,让它们能组合出 50 种玩法。
Jonathan Blow(Braid、The Witness):解锁技能应让人觉得自己理解了新事物,而不是填满了进度条。如果玩家解锁后没有觉得自己更聪明或更强大,那么这个节点就白费了。
来源
- 《设计科技树与成长系统》——2016 年 GDC,Chris Taylor
- 《游戏设计的艺术》——Jesse Schell,关于技巧与机遇的章节
- 《多人游戏中的能力系统平衡》——2019 年 GDC
- 《简单系统催生的涌现式玩法》——Will Wright,GDC 经典演讲
- 《成长设计中的玩家自主性》——2020 年 GDC