运行时、宿主与平台接入
这一页不是写给“如何写剧情”的,而是写给这些人:
- 游戏工作室技术负责人
- Web / Native 渲染器开发者
- 想把 NovaMark 接到自己产品里的团队
如果你关心的是:
- VM 到底怎么推进
- 为什么 UI 不应该由脚本控制
- 运行时状态怎么给前端使用
- Web 模板和 C API 分别适合什么场景
那这页就是新的主入口。
1. 先理解 NovaMark 的运行模型
NovaMark 当前不是连续时间动画引擎,而是一个:
离散状态机 + 宿主控制渲染与推进
这句话非常重要。
它意味着:
- 引擎不会自己持续播放“时间轴”
- 引擎不会自己控制 HUD
- 引擎不会自己决定何时弹存档 UI
- 引擎不会自己决定动画过渡持续多久
引擎做的事情是:
- 根据脚本推进到下一个离散状态
- 产出当前应该展示的状态快照
- 等宿主决定下一步要做什么
2. 什么叫“离散状态”
NovaMark 当前最核心的宿主动作只有两种:
advance()choose(choiceId)
advance()
表示:
请继续推进,直到下一个需要宿主处理的状态点。
例如:
- 一段新的对话出现
- 一个选择出现
- 一个结局出现
choose(choiceId)
表示:
玩家已经选中了某个选项,请按它继续剧情。
宿主不需要知道内部如何“消费对话”,也不需要理解引擎内部停顿细节。
这就是 NovaMark 当前对外 API 的原则:
宿主表达意图,引擎负责状态推进。
3. 宿主和脚本如何分工
这是 NovaMark 最重要的设计边界之一。
脚本负责
- 剧情内容
- 场景与跳转
- 条件分支
- 状态变化
- 资源引用
- 检定与选择逻辑
宿主负责
- UI 布局
- 对话框样式
- HUD
- 动画
- 打字机效果
- 存档时机
- 文件管理
- 平台适配
这意味着同一份内容可以被不同平台消费:
- Web 模板可以渲染成聊天界面
- Native 端可以渲染成视觉小说界面
- CLI 端可以渲染成文字模式
脚本不需要知道这些差异。
4. 什么是运行时状态
NovaMark 的运行时状态就是宿主真正要消费的数据。
它通常包括:
- 当前场景/标签
- 变量
- 背包
- 角色定义
- 物品定义
- 对话
- 选项
- 背景
- BGM
- 立绘
- 文本配置
宿主拿到这些状态后,就可以自己决定:
- 怎么显示
- 显示到哪里
- 用什么动画表现
所以从平台接入视角看,NovaMark 更像:
一个叙事状态提供者
而不是“UI 框架”。
5. 为什么 transition / position / opacity / loop / volume 只是渲染提示
你会看到脚本里有这些字段:
transitionpositionopacityloopvolume
这些字段保留,是为了表达创作者意图;但它们不代表引擎内部拥有完整时间轴系统。
正确理解方式
它们是:
- 渲染提示
- 可消费的状态字段
不是:
- 引擎自动执行的连续动画
- 引擎内部媒体时间流控制器
这正是平台接入方应该注意的点:
这些字段应该由你的宿主平台来解释和呈现。
6. Web 模板的定位是什么
NovaMark 当前提供的 Web 模板,不是“唯一正确的前端”,而是:
- 一套参考实现
- 一套可运行示例
- 一套告诉你宿主应该怎么消费 runtime state 的模板
你可以把它理解成:
最小但完整的接入示范
它适合:
- 快速试玩
- 对照运行时状态结构
- 理解
advance()/choose()的宿主职责
关于 Web 模板的详细说明,请参阅 Web 模板文档。
但如果你是工作室或平台方,完全可以用它作为参考,再接自己的:
- Native UI
- 商业发行前端
7. C API 的作用是什么
如果你不想直接在 C++ 层绑内部类,而是想走一个更稳定的宿主接口层,那 C API 是更好的入口。
它适合:
- C/C++ 集成
- 跨语言绑定
- WASM 导出
- NAPI / JNI / FFI 封装
目前你可以把它看成:
平台接入层的标准宿主接口
它的职责不是暴露所有内部实现,而是给宿主稳定地做这些事:
- 创建与销毁 VM
- 加载包
- 推进剧情
- 选择选项
- 读取状态
- 保存与恢复快照
关于 C API 的详细文档,请参阅 C API 参考。如需 Web 平台绑定,请参阅 WASM API。
8. 存档在平台接入层应该怎么理解
NovaMark 当前已经把存档分成两层:
正式文件存档
- 二进制格式
- 给玩家和产品环境使用
JSON 快照
- 调试格式
- 测试格式
- Web/WASM 开发工具格式
所以对于平台接入方,推荐的理解方式是:
- 正式游戏存档 → 二进制
- 调试与开发 → JSON
9. 如果你是工作室 / 发行方,推荐接入顺序
第一步:先接包加载和运行时推进
先确保:
load packageadvance()choose(choiceId)
这条链路能走通。
第二步:接运行时状态
先把以下状态接到你们前端:
- dialogue
- choices
- bg
- sprites
- variables / inventory
第三步:再接渲染提示字段
比如:
transitionpositionopacityloopvolume
第四步:最后接存档
建议先用 JSON 调试快照跑通,再接正式二进制存档。
10. 你接下来该看什么
如果你是平台接入方,建议继续看:
如果你是创作者,请回到: