GoNorth导出引擎深度解析:Scriban模板、占位符与Export Snippets原理揭秘
GoNorth导出引擎深度解析:Scriban模板、占位符与Export Snippets原理揭秘
【免费下载链接】GoNorthGoNorth is a story and content planning tool for RPGs and other open world games.项目地址: https://gitcode.com/gh_mirrors/go/GoNorth
GoNorth是一款面向 RPG 与开放世界游戏的故事与内容规划工具,而它最硬核的亮点之一就是内置的导出引擎:你可以在 GoNorth 里设计 NPC、道具、对话、任务与状态机,再通过Scriban 模板、占位符和 Export Snippets把规划好的内容一键转换为可直接使用的游戏脚本(如 Lua)。本文带你从零看懂这套导出引擎的工作原理 🎮
🧭 一图看懂:导出引擎解决什么问题
在传统的游戏开发流程中,策划写策划案、程序写脚本,两者之间靠"人肉翻译"。GoNorth 的导出引擎把这一环节自动化了:
- 📝输入:你在界面上配置的对象数据(NPC 属性、背包、技能、对话、日常行为等)
- 🧩模板:你(或默认提供的)Scriban 导出模板,定义"输出长什么样"
- ⚙️引擎:占位符解析 + 数据收集器 + 函数渲染器
- 📤输出:结构完整、可运行的游戏脚本
入口非常简洁,整个导出行为都围绕 IObjectExporter 接口展开,一次导出只需要两个参数:模板(ExportTemplate)和对象数据(ExportObjectData)。
🏗️ 模板数据模型:一切导出的起点
每个导出模板对应一条数据库记录,核心定义在 ExportTemplate.cs 中。理解这 4 个字段,就理解了导出引擎的骨架:
| 字段 | 作用 |
|---|---|
TemplateType | 模板类型(对象、对象 Snippet、Include、每日行为等),决定哪些数据可用 |
Code | 模板正文,即 Scriban 模板代码 |
RenderingEngine | 渲染引擎:Legacy或Scriban |
ExportSnippets | 模板上挂载的 Export Snippets 列表 |
其中RenderingEngine是一个枚举,定义在 ExportTemplateRenderingEngine.cs 中:
- Legacy(旧引擎):基于占位符解析器的老式方案,占位符由一组
PlaceholderResolver逐个替换,逻辑写死在 C# 代码里 - Scriban(新引擎):基于 Scriban 模板引擎的现代方案,模板本身具备完整的条件、循环和函数能力,灵活性大幅提升
💡 旧模板默认使用 Legacy 引擎以保证向后兼容;新模板建议直接使用 Scriban。
🔍 Scriban 渲染引擎内部:占位符是如何被填上的
核心实现位于 ScribanExportTemplatePlaceholderRenderingEngine.cs。一次导出的流程可以概括为 4 步:
- 解析模板:
Template.Parse把模板代码解析为 Scriban 模板,并在保存时提前校验语法 - 构建脚本对象:遍历一组值收集器(Value Collector),把数据库中的对象数据"注入"到模板可用的数据上下文中
- 渲染:调用
RenderAsync,把模板 + 数据渲染为最终脚本文本 - 错误收集:所有异常统一汇入错误集合,界面上可看到清晰的错误提示
值收集器:模板里每个变量从哪来
引擎内置了十几个IScribanExportValueCollector实现(目录:Services/Export/Placeholder/ScribanRenderingEngine/ValueCollector/),每个收集器负责一类数据:
NpcExportValueCollector→ 模板里的npc(名称、属性、状态机)ItemExportValueCollector→item(道具数据)InventoryValueCollector/ItemInventoryValueCollector→ 背包列表DialogValueCollector→dialog(对话图与全部对话函数)NpcStateMachineExportValueCollector→state_machine(状态与迁移)NpcDailyRoutineExportValueCollector→daily_routine(日常行为)ExportSnippetValueCollector→snippet/snippet_function(Export Snippets)LanguageKeyValueCollector→langkey(多语言键值)
也就是说:模板里的变量不是魔法,而是这些收集器提前收集好并注册进 Scriban 的ScriptObject。
管道函数:把复杂数据"一行变多行"
除了变量,Scriban 模板还能使用内置的管道渲染函数(实现位于Services/Export/Placeholder/ScribanRenderingEngine/RenderingFunctions/)。以默认的 NPC 模板 ObjectNpc.lua 为例(节选):
-- Inventory {{ inventory | inventory_list }} -- Skills {{ skills | skill_list }}| inventory_list会把背包数据渲染成多行、带缩进的游戏代码;类似的函数还有attribute_list(属性列表)、skill_list、daily_routine_event_list、dialog_function、state_machine_function、indent_multiline(多行缩进)等。
条件与循环:Scriban 让模板"会思考"
Scriban 引擎让模板拥有了真正的逻辑能力,默认模板中随处可见:
{{~ if !inventory.empty? ~}} {{ inventory | inventory_list }} {{~ end ~}} {{~ if dialog ~}} {{~ for curFunction in dialog.all_functions ~}} {{ curFunction | dialog_function }} {{~ end ~}} {{~ end ~}}翻译过来就是:"如果这个 NPC 有背包,就导出背包;如果配置了对话,就遍历导出所有对话函数"。这种按需输出的能力,Legacy 引擎是做不到的 🚀
📚 默认模板库与 include 机制
GoNorth 自带一套开箱即用的默认模板,全部放在DefaultExportTemplates/目录下,按用途组织:
Object/:NPC、道具、技能、背包、状态函数等对象模板(ObjectNpc.lua)Tale/:对话系统的动作与条件模板(TaleAction*.lua、TaleCondition*.lua,近百个)General/:通用的条件比较与逻辑运算模板(等于、包含、与/或/非……)Language/:语言文件(ini)导出模板
配合include 机制,模板可以像"积木"一样复用:Scriban 模板中一行include "Npc"就能引入另一个模板的内容,底层由 ScribanIncludeTemplateLoader.cs 负责从数据库加载。默认模板的加载则交给 CachedExportDefaultTemplateProvider.cs 做缓存管理。
🧩 Export Snippets 原理揭秘:给对象挂上"自定义脚本"
Export Snippets是 GoNorth 导出体系中最灵活的设计:你可以给任意对象挂上一个独立的小脚本片段,导出时它会自动生成一个带函数名的代码块,嵌入到对象脚本中。
两种 Snippet 写法,一条渲染管线
渲染逻辑集中在 ExportSnippetFunctionRenderer.cs,它支持两种ScriptType:
| 类型 | 说明 |
|---|---|
| Code(代码型) | 直接填写脚本文本,原样包装成函数导出 |
| NodeGraph(节点图型) | 用可视化节点编排逻辑,引擎调用INodeGraphParser解析节点图,复用对话系统的步骤渲染器,把节点"翻译"成脚本函数 |
无论哪种写法,最终都会产出一个ExportSnippetFunction(函数名 + 函数体),再交给默认模板 ObjectExportSnippetFunction.lua 输出:
function {{ snippet_function.function_name }}(this) {{ snippet_function.code | indent_multiline }} endSnippet 与对象"互相感知"
Services/Export/ExportSnippets/目录下还有一组配套服务:
- ExportSnippetFunctionNameGenerator.cs:自动为 Snippet 生成不冲突的函数名
- ExportSnippetRelatedObjectNameResolver.cs:解析 Snippet 引用的关联对象(比如某段逻辑针对的 NPC 或道具)
- ExportSnippetRelatedObjectUpdater.cs:对象被导出时,让相关 Snippet 自动同步
🌐 多语言导出:langkey 占位符
游戏文本需要多语言支持,GoNorth 的方案是语言键(Language Key):
- 模板中写
{{ langkey npc.name }},而不是直接输出角色名字文本 - ScribanLanguageKeyGenerator.cs 负责为每个待导出文本生成唯一的语言键
- 导出的 ini 语言文件由
Language/LanguageFile.ini模板渲染,LanguageKey数据模型定义在 LanguageKey.cs
这样,脚本里引用的是稳定的键值,具体文案集中在语言文件中维护——本地化流程一目了然 🌍
🚀 快速上手:三步写出你的第一个 Scriban 导出模板
- 新建模板:在导出模板管理页创建模板,渲染引擎选择Scriban
- 写模板代码:从"占位符"面板查看当前模板类型可用的变量(如
npc、inventory、dialog)与函数,善用{{~ if ~}}、{{~ for ~}}控制输出 - 选对象导出:在对象详情页选择你的模板执行导出,界面对照预览生成的脚本;语法错误会在保存时由
ValidateTemplate提前拦截
💡 小贴士:不确定语法?直接把
DefaultExportTemplates/Object/下的默认模板抄一份来改,是最快的学习路径。
✅ 总结
| 组件 | 一句话定位 |
|---|---|
| ExportTemplate | 导出行为的配置中心:类型、代码、引擎、Snippets |
| Scriban 引擎 | 变量注入 + 条件循环 + 管道函数,模板即逻辑 |
| 值收集器 | 把数据库对象"翻译"成模板变量 |
| Export Snippets | 对象级自定义脚本,支持代码与节点图两种写法 |
| langkey | 文本与脚本解耦,支撑多语言导出 |
GoNorth 的导出引擎用"模板 + 数据 + 渲染函数"三层设计,把策划内容与游戏脚本之间的手工鸿沟彻底填平。理解了占位符、Scriban 模板与 Export Snippets 这三块拼图,你就掌握了它的核心 🏁
【免费下载链接】GoNorthGoNorth is a story and content planning tool for RPGs and other open world games.项目地址: https://gitcode.com/gh_mirrors/go/GoNorth
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
