Files
Genarrative/docs/experience/PROJECT_WORK_EXPERIENCE_PLAYBOOK.md
高物 ddcb5d5c8c
Some checks failed
CI / verify (push) Has been cancelled
Rework story engine flow and reorganize project docs
2026-04-06 23:19:00 +08:00

9.9 KiB
Raw Blame History

奇幻酒馆项目开发经验手册

日期:2026-03-24

1. 项目本质判断

这个项目不是单纯的前端页面项目,也不是单纯的大模型接入项目,而是 4 条链路同时存在的复合型项目:

  1. 叙事链路:剧情文本、选项文本、角色对话、聊天上下文。
  2. 状态链路角色、怪物、NPC、场景、背包、装备、战斗状态、CD、蓝耗、死亡、掉落。
  3. 演出链路:角色进场、近战贴身、受击、死亡、逃跑、镜头跟随、场景切换、前探预览。
  4. 工具链路NPC 形象编辑器、行为编辑器、预设数据、校验脚本、本地调试环境。

经验结论:

  • 任何需求只要影响两条以上链路,就不能只改 UI。
  • 先判断需求落在哪些链路,再决定改哪些文件。
  • 这类项目最怕“看起来改好了”,但状态、动画、提示词和运行逻辑其实没对齐。

2. 架构拆分经验

已经验证更稳的结构是:

  • App.tsx 保持尽量薄,只做外层挂载。
  • GameShell.tsx 负责主流程壳层:开始页、世界选择、角色选择、游戏内主界面切换。
  • 各类状态和流程尽量放进 hooks
    • useGameFlow
    • useCombatFlow
    • useStoryGeneration
    • useNpcInteractionFlow
    • useInventoryFlow
    • useEquipmentFlow
  • 各类独立 UI 面板拆成独立组件:
    • AdventurePanel
    • CharacterPanel
    • InventoryPanel
    • MapModal
    • AdventureEntityModal

经验结论:

  • 按职责拆,不按文件长度拆。
  • 状态修改尽量集中在 hook 内,不要散落在多个按钮回调里。
  • 预览系统、编辑器系统、正式游戏流程要尽量复用同一套业务逻辑,而不是各写一套。

3. AI 与本地规则的边界

目前最稳定的边界是:

  • AI 负责生成:
    • storyText
    • actionText
    • 对话文本
    • 基于上下文的语气、叙事张力、选项措辞
  • 本地规则负责决定:
    • 哪些 function 当前可执行
    • 技能是否在 CD
    • 蓝量是否足够
    • 伤害、回复、掉血、死亡、掉落
    • 场景切换是否合法
    • 背包、装备、属性、队伍变化

经验结论:

  • 涉及数值、资源、状态迁移的部分,不要交给模型临场决定。
  • 模型应被限制在“叙事表达层”,不要替代规则系统。
  • 用户每次选择后只做一次模型推理,因此提示词必须一次性包含足够边界,不能再依赖后处理改写和过滤。

4. Function 驱动设计经验

当前更合理的设计方向是:

  • 所有可选行为都落到 function。
  • 每个 function 只有这些核心字段:
    • id
    • text
    • description
    • category
    • 功能代码
  • 运行时先汇总当前场景的 function再结合角色、状态、敌人、场景实体、资源状态做合法性过滤。
  • 模型只在“当前合法 function 集合”内生成选项文本和剧情文本。

经验结论:

  • 选项不是自由散文,而是 function 的叙事包装。
  • function 必须和角色、状态、场景、实体绑定,不能做成完全漂浮的公共动作池。
  • “每次选择只能并且必须命中一个 function” 是保持状态稳定的关键。

5. 战斗与动画的经验

战斗部分已经沉淀出的几个重要规则:

5.1 结算时机

  • 用户点击选项后,后台状态应立即推进到“动画完成后的结果状态”,并把这个新状态放入后续推理上下文。
  • 但扣血、死亡表现、消失等视觉结果要在动画播完后再体现在画面上。

这样做的好处:

  • 模型推理可以立即开始,不被动画阻塞。
  • 画面依然保留正确的演出节奏。
  • 状态、上下文、下一轮推理不会落后于动画。

5.2 近战位移

  • 近战动画不能按固定像素移动。
  • 必须按左右锚点、舞台宽度和目标位置计算真实接近距离。
  • 宽屏下如果只“往前走一点点”,基本就是位移基准用了屏幕百分比或固定偏移,而不是双方真实锚点差值。

5.3 死亡与退出战斗

  • 怪物血量归零时先播死亡动画。
  • 死亡动画完成后怪物再消失。
  • 若敌方死亡,战斗状态应退出,切回空闲状态,并重新切换可用 function 集合。

5.4 逃跑与压迫感

  • 逃跑镜头要跟着玩家,不是跟怪物。
  • 玩家向前跑,怪物被越甩越远,才能形成“甩开追兵”的感觉。
  • 相反,如果镜头锚在怪物侧,会让玩家像没动一样。

6. 遭遇、场景与地图经验

这部分已经验证有效的设计原则:

  • 场景和背景图一一绑定,不切场景就不换背景。
  • 场景切换必须由选项命中的 function 驱动,而不是每回合自动变化。
  • 每个场景预设自己的怪物、NPC、宝藏池。
  • 玩家“继续向前探路”时,不是立刻随机弹结果,而是先预生成前方实体,再通过移动和镜头演出把它带到正式交互位。

经验结论:

  • “探索”也应该是一种可演出的 function而不只是一次文字刷新。
  • 同一时刻只应遇到一个主实体,避免一回合同时出现多只怪物造成状态混乱。
  • 地图系统适合做成场景连接图,由具体 function 触发前往某个场景。

7. 移动端优先的 UI 经验

已经验证有效的 UI 方向:

  • 先保证移动端一屏成立,再兼容网页宽屏。
  • 开始页、世界选择、角色选择都要像游戏流程,而不是产品介绍页。
  • 世界选择适合纵向焦点滑动。
  • 角色选择适合横向翻卡和中心焦点展示。
  • 冒险页中:
    • 上方是画面演出
    • 中间是自适应剧情文本
    • 底部是固定的选项与功能入口

经验结论:

  • 剧情区域不能写死高度,应填满画面下方和底部操作条上方之间的剩余空间。
  • 队伍、背包更适合作为弹出面板,不应该切走主流程。
  • 地图弹窗、队伍面板、背包详情都必须按手机窄屏重新组织,不要沿用桌面弹窗思路。

8. 选择页与游戏内界面经验

这轮迭代里比较明确的 UI 结论有:

  • 开始页只保留核心按钮,视觉简洁更像正式游戏。
  • 世界选择页要突出当前聚焦卡,其他卡随滑动连续改变透明度和大小。
  • 角色选择页中:
    • 中间卡片不能模糊
    • 左右卡片要做正确方向的倾斜
    • 中间角色可播放 run 动画
    • 角色名称显示在动画下方
    • 属性和背景信息要紧凑,不能压缩掉上方卡片滑动空间
  • 游戏内按钮应尽量图标化,把更多空间留给剧情和选项。

9. NPC 形象编辑器经验

NPC 编辑器这部分已经沉淀出一些通用原则:

  • 这套 Medieval Fantasy Characters 素材不是传统逐帧全身序列帧,发型、脸型、胡子、武器等部件不能按“每帧都变化”的思路处理。
  • 主手武器、副手武器、手、身体、头部、头饰需要明确图层关系。
  • 主手武器必须真正握在手里,不能只靠大概位置“看起来差不多”。
  • 因为素材高度重叠,编辑器里必须支持:
    • 底部组件模块点击选择
    • 键盘上下左右微调
    • 拖拽微调
    • 回滚按钮

经验结论:

  • 视觉编辑器如果没有“可控选择 + 微调 + 回滚”,用户会很难调重叠素材。
  • 选项命名不能直接暴露英文源文件名,最好转成更贴近视觉理解的中文名称。
  • 编辑器产出的相对位置数据必须能直接落回项目运行时,不然就只是一个孤立工具。

10. 大模型接入与本地调试经验

这部分踩坑非常集中,结论也比较清晰:

10.1 前端不能直连目标模型接口

  • 浏览器直连时会遇到 CORS。
  • 即使接口本身可用,浏览器环境也可能被跨域限制。
  • 更稳的方案是在开发服务器侧做代理,再由前端请求本地 /api/llm/...

10.2 需要日志,但日志要聚焦

已经证明有价值的日志包括:

  • 单次推理耗时
  • 原始提示词文本
  • 原始返回中的解析后文本
  • 失败时的模型名、状态码和错误正文

10.3 开发服务器要统一入口

本项目本地正确启动方式应统一走:

node scripts/vite-cli.mjs --port=3000 --host=0.0.0.0

经验结论:

  • 只要本地存在旧进程、旧脚本或错误端口映射,就很容易出现“代码改了但界面还是旧的”假象。
  • 遇到这类问题,优先检查实际启动脚本、端口占用和返回模块内容,而不是先怀疑 UI 代码没生效。

11. 编辑器与正式运行时的关系

已经验证最稳的做法是:

  • 编辑器预览直接复用正式运行时函数。
  • 预览不自己模拟一套战斗和 function 执行逻辑。
  • 运行时怎么结算,编辑器就怎么调用。

经验结论:

  • 只要编辑器预览和正式逻辑分成两套,后面一定会越来越不一致。
  • 预览系统的价值不是“看起来像”,而是“执行路径就是正式路径”。

12. 后续继续开发时建议遵循的顺序

推荐流程:

  1. 先补数据结构和类型。
  2. 再补 function 规则和过滤条件。
  3. 再补 hook 流程与状态迁移。
  4. 再补动画和演出。
  5. 最后再做 UI 细修。
  6. 每轮改动后至少做一次类型检查和本地启动验证。

不推荐的流程:

  1. 先堆 UI。
  2. 再临时塞状态。
  3. 最后补运行逻辑。

这类项目里,后者几乎一定导致返工。

13. 一句话总结

这个项目最重要的经验不是“做了多少页面和功能”,而是:

必须把 AI 文本生成、本地规则、动画演出、场景状态、编辑器工具这几套系统严格分层,再通过 function 和统一状态流把它们重新接起来。

14. 相关文档

如需继续细看已有沉淀,可结合以下文档一起阅读:

  • docs/experience/PROJECT_DEVELOPMENT_EXPERIENCE.md
  • docs/experience/MOBILE_UI_DEV_EXPERIENCE.md
  • docs/experience/CODEX_IMPLEMENTATION_EXPERIENCE_2026-03-24.md
  • docs/experience/AGENT_UI_CHANGELOG.md