# AI Native Visual RPG 开发经验沉淀 ## 1. 项目特点判断 这个项目不是单纯的“像素 UI 项目”,而是 4 条链路同时耦合的项目: 1. 叙事链路:AI 生成剧情文本与选项 2. 状态链路:玩家、怪物、NPC、背包、好感、同伴、场景流转 3. 演出链路:战斗计划、动画播放、投射物、特效、镜头位移 4. 界面链路:选择世界、选择角色、冒险页、背包页、地图弹窗、编辑器页 经验: - 做功能前先判断它主要影响哪几条链路。 - 如果一个需求同时影响“状态 + 演出 + UI”,不要只改一个点。 - 像“初始同伴”这种功能,本质上不是 UI 需求,而是“选角流程 + 初始 encounter + NPC 好感 + 招募状态”的组合需求。 ## 2. 先做数据建模,再做 UI 这一类项目最容易犯的错误,是先加按钮、再补状态。 实践下来更稳的顺序是: 1. 先把状态字段补齐 2. 再补工具函数 3. 再接交互入口 4. 最后补展示层 已经验证有效的状态字段包括: - `playerInventory` - `npcStates` - `companions` - `currentBattleNpcId` - `currentEncounter` - `playerActionMode` - `activeCombatEffects` 经验: - “能否交易 / 能否招募 / 送礼涨多少好感”都应该由状态和规则函数决定,不能写死在按钮文本里。 - NPC 交互尽量走本地规则,不要依赖 AI 即时决定关键数值。 ## 3. 复杂页面一定要拆流程层 `App.tsx` 一旦同时承载: - 游戏主状态 - 剧情生成 - 战斗播放 - NPC 交互 - 地图 - 选角 就会迅速失控。 当前更合理的分层思路是: - `useGameFlow` 负责基础游戏状态、世界选择、角色选择、初始进入逻辑 - `useCombatFlow` 负责战斗计划与播放 - `useStoryGeneration` 负责剧情生成、NPC 本地交互分流、选项池管理 - `useNpcInteractionFlow` 负责同伴/NPC 展示态 - `GameShell` 负责主容器与选择流程 - `AdventurePanel` 负责冒险页文本和选项 - `NpcModals` 负责交易 / 送礼 / 放生招募等弹窗 经验: - 流程层优先按“职责”拆,不按“文件长度”拆。 - 状态修改逻辑尽量集中到 hook 内,不要散落在多个组件按钮回调里。 ## 4. AI 只适合生成叙事,不适合决定关键规则 实践中最稳定的策略是: - AI 负责: - `storyText` - 非 NPC 关键规则的普通探索选项文案 - 本地规则负责: - NPC 交互选项 - 交易合法性 - 礼物好感值 - 招募阈值 - 战斗掉落 - 帮助奖励 经验: - 凡是会影响数值平衡、背包物品、好感、队伍成员的部分,都不要交给 AI 即时决定。 - AI 生成内容要能被本地规则兜底,否则体验会不稳定。 ## 5. NPC 系统要“角色型 NPC”和“普通 NPC”分开处理 项目里 NPC 实际上有两种: 1. 普通场景 NPC:可用通用 Medieval NPC 渲染 2. 角色型 NPC:应该复用玩家角色对应的立绘和动画 经验: - 只看 `encounter.kind === 'npc'` 不够,还要看 `encounter.characterId`。 - 有 `characterId` 的 NPC,应该优先走 `CharacterAnimator`。 - 否则就会出现: - 选了某个同伴,但开场看到的是另一套通用 NPC 外观 - 战斗里角色型 NPC 看起来像普通路人 ## 6. 位置与朝向必须统一到一套坐标规则 这是这类项目里最容易反复返工的点。 实践中踩过的坑: - `sceneMonsters` 用一套坐标逻辑 - `currentEncounter` 用另一套坐标逻辑 - 结果开场 NPC 和遇怪站位不一致 - 角色型 NPC 立绘比怪物更容易出现“脚没落地”“太小”“翻转方向错” 最终经验: - 对面实体的横向定位必须统一到“怪物那套 world-space 逻辑” - 也就是: - 位置统一用怪物侧的 anchor - 相机平移时统一跟随同一套计算 - 角色型 NPC 的垂直位置不能偷懒固定 - 应该结合角色自身 `groundOffsetY` - 朝向规则要统一使用 `getFacingTowardPlayer` 一句话总结: - 角色型 NPC 不应该单独发明一套站位系统,而应该尽量复用怪物对位系统。 ## 7. “新增流程”不要破坏原有选择 UI 这次初始同伴功能就是一个典型经验: - 用户原本对“选择扮演角色”的视觉和交互已经形成预期 - 如果为了加“初始同伴选择”直接把角色选择页改成另一种样式,会造成明显割裂 经验: - 新流程优先插在旧流程后面,而不是重写旧流程 - “确认角色 -> 选择初始同伴 -> 进入冒险”比“把原选角页改成全新样式”风险小很多 - 如果必须改 UI,也要尽量保留旧页面的视觉结构和交互节奏 ## 8. 冒险页布局要优先保证画面和选项完整可见 冒险页真正的优先级是: 1. 上方画布要在一屏内正常显示 2. 下方 3 个选项要在一屏内正常显示 3. 剧情文本框剩余空间自适应 经验: - 文本框不能无限长撑开 - 正确做法是: - 文本框高度自适应剩余空间 - 文本超长时内部滚动 - 不能让 `storyText` 把战斗画面和选项挤出首屏 ## 9. 编辑器页和玩家页要明确隔离 当前项目里存在编辑器页面: - `PresetEditor` - `NpcVisualEditor` - `StateFunctionEditor` 玩家页和编辑器页的需求完全不同。 经验: - 像字体切换、视觉统一这种全局改动,不要直接打到整个站点 - 应该只挂在非编辑器根容器上 - 比如 `fusion-pixel-app` 这种类,只挂在正式游玩界面,不挂在编辑器根节点 ## 10. 构建环境问题要项目内消化 实际踩到的构建问题: - Node 16 环境下,Vite 构建会因为 `crypto.getRandomValues` 缺失报错 沉淀出的解决方式: - 不强依赖开发机立刻升级 Node - 在项目内增加 Vite 启动包装脚本 - 统一让 `dev / build / preview` 都走这层 shim 经验: - 环境兼容问题如果能在项目内吸收,就尽量不要把负担转移给每个协作者 - 文档里要明确记录“为什么这样做” ## 11. 比较稳的开发顺序 后续继续扩展功能时,建议遵守这个顺序: 1. 写状态字段 2. 写规则工具函数 3. 写流程 hook 4. 接 UI 5. 跑 `npm run lint` 6. 跑 `npm run build` 7. 再做视觉微调 不要反过来做: - 先做 UI - 再补状态 - 最后硬修流程 这种顺序在状态复杂的项目里会越改越乱。 ## 12. 当前最值得继续坚持的原则 - 保持 AI 生成和本地规则分工清晰 - 保持角色型 NPC 与普通 NPC 的渲染分流 - 保持“怪物 / encounter / 战斗 NPC”统一坐标系 - 保持新增功能不破坏既有核心 UI 体验 - 保持编辑器页与玩家页隔离 - 每次大改后都用 `lint + build` 双重验证 ## 13. 后续建议 下一阶段最值得继续沉淀的方向: 1. 把 NPC 交互逻辑继续从 `useStoryGeneration` 中独立成更纯粹的 `useNpcInteractionFlow` 2. 把角色型 NPC 的位置、缩放、贴地参数做成可配置规则,而不是继续散落在画布里微调 3. 针对初始同伴流程补一份单独的状态图 / 时序图 4. 对大 chunk 警告做代码分包 ## 14. 一句话总结 这个项目真正的开发经验不是“怎么多写一个按钮”,而是: - 在 AI 叙事、像素演出、战斗状态、NPC 规则、选择流程和编辑器体系同时存在的情况下,始终让每条链路各归其位。