LetsGal Studio 的剧本以 JSON 文件保存在工程目录里。本页先定义章节、Fragment、Block 的磁盘结构,再给出指令全参考。这里描述的是 Studio 工程源文件,不是编译后的运行时 OP 数据,也不是 Studio 内置 AI 的流式协议。
想让 AI 帮你写剧本?先看下面的最小示例,再把本页和工程实体对照表一起交给 AI。生成后按页尾检查清单核对结构、类型和引用;缺少资源信息时,让 AI 报告缺项,不要猜 id。

工程里的剧本文件

一个 Studio 工程的根目录下,与剧本相关的文件如下:
路径内容
project.json工程配置与章节索引(章节顺序、目录结构)
chapters/*.json剧本正文。每个章节一个文件,文件名就是章节名(如 chapters/序章.json)
characters.json角色定义:id、名字、表情、皮肤、属性模板
scenes.json场景定义:id、名字、图层
project.variables.json全局变量表:id、名字、类型、默认值
assets/素材文件,按分类分子目录(bgm/、se/、video/ 等)
几条基本规则:
  • 改章节名时,章节文件也会跟着改名;文件名与 JSON 里的 name 字段始终一致。
  • project.json 的 chapterOrder 是一个章节名数组,决定章节的运行顺序;新章节文件必须登记进去才会被工程识别。
  • chapterOrder 的第一项是入口章节(工程模板里叫「开始」),不可删除。
  • project.json 里还有 chapterFolders(编辑器里的虚拟目录)和 chapterTreeOrder(章节树根层排序)。目录不改变章节文件路径,但在 Studio 整理章节树后,展开顺序会同步到 chapterOrder;不要生成互相矛盾的排序。

先复制这个最小章节

以下是一个完整、合法、不依赖角色、场景、音频或变量的章节文件。保存为 chapters/最小示例.json;复制多份时请替换章节和片段 id,避免重复。
{
  "id": "ch-example-minimal",
  "name": "最小示例",
  "fragments": [
    {
      "id": "frag-example-main",
      "name": "main",
      "blocks": [
        {
          "type": "narration",
          "props": { "keepDialogue": false },
          "content": [
            { "type": "text", "text": "故事从这里开始。", "styles": {} }
          ]
        },
        { "type": "endChapter", "props": {} }
      ]
    }
  ]
}
在已有工程的 project.json 中,把 最小示例 加入原有的 chapterOrder,保留入口章节和其他配置。下面只是索引片段,不能作为完整的 project.json 覆盖工程配置:
{ "chapterOrder": ["开始", "最小示例"] }
这个示例会显示一句旁白,然后结束本章。只需要空章节骨架时,把 blocks 改为 [] 即可;不需要用 paragraph 占位。独立 Fragment 或 Block 对象都不能直接替代整个章节文件。

章节文件的结构

每个 chapters/*.json 的顶层结构:
{
  "id": "ch-1755500000000-1",
  "name": "第一章",
  "fragments": [
    { "id": "frag-1755500000000-2", "name": "main", "blocks": [] }
  ]
}
字段JSON 类型生成时必填默认值 / 缺省行为约束
idstring是无;生成器必须提供非空、全工程唯一。Studio 新建时使用 ch-<毫秒时间戳>-<序号>;这是生成习惯,不是必须匹配的正则,也可使用 UUID。修改现有章节时保留原 id
namestring是无非空,与文件名去掉 .json 后完全一致;避免文件系统不允许的字符。工程内章节名不能重复
fragmentsFragment[]是无;新建章节会创建一个 main 片段至少一个元素,第一项名称必须为 main;不要输出空数组或 null
disabledboolean否缺省视为 falsetrue 停用章节;入口章节不应停用。不是字符串 "true"
kindstring否省略表示普通章节仅特殊前处理章节使用 "schedule-preprocessing";没有 "normal" 等其他约定值。普通剧情生成时省略
kind 属于高级章节调度。不要为了“补齐默认值”给普通章节添加此字段,也不要用 null 表示普通章节。

剧情片段

剧情片段在编辑器里叫 Fragment,是章节内的执行单元:
{
  "id": "frag-1755500000000-2",
  "name": "main",
  "blocks": []
}
字段JSON 类型生成时必填默认值 / 缺省行为约束
idstring是无;生成器必须提供非空、全工程唯一。Studio 新建时使用 frag-<毫秒时间戳>-<序号>,也可使用其他唯一字符串;引用填写 id,不是片段名
namestring是无第一项固定为 main;其他片段使用非空名称,不要再命名为 main
blocksBlock[]是新建片段为 [];生成时显式填写指令按数组顺序执行;空数组合法。不能改成对象、字符串或 null
metadataobject否无片段级附加配置非执行元数据。普通片段省略;修改已有片段时保留原配置。这里是真对象,不是 JSON 字符串
片段没有通用 disabled、next、nextFragmentId、chapterId 或 type 字段,不要自行添加这些字段控制执行。停用单条指令用 block.props.disabled,停用整章用 chapter.disabled。

片段元数据 metadata

普通线性剧情不需要 metadata。蓝图中的扩展调度策略可以使用 metadata.scheduleEvent:
字段JSON 类型必填默认值 / 约束
metadata.scheduleEventobject否省略表示没有在此处配置调度事件
scheduleEvent.strategyTargetstring配置事件时必填无默认值;必须是工程实际使用的调度策略全局 id
scheduleEvent.enabledboolean否缺省视为 true;false 保留配置但不加入调度事件池,不是片段通用停用开关
scheduleEvent.configobject配置事件时必填字段由该调度扩展的 schema 定义,无通用默认结构,不能由 AI 猜测
metadata 还允许扩展附加配置。保留已有未知配置;需要新增时,先取得对应扩展的字段规范。

执行模型:默认线性链

以下描述基础线性调度;启用蓝图调度时,章节选取还受工程调度配置控制:
  1. 章节从 main 片段的第一个 Block 开始,顺序执行;一个章节执行完,进入 chapterOrder 里的下一章。
  2. 跳出线性流的手段只有三种指令:branch(玩家选项)、if(条件跳转)、callFragment(直接调用片段)。它们的目标都是同一章节内的非 main 片段。
  3. 跳转到的片段执行完毕后,回到原跳转点之后继续(汇流回主线),类似函数调用。片段之间不要循环引用。

指令的通用结构

生成内置剧本指令时,使用以下通用字段:
{
  "id": "66d4d76d-ddec-4f99-836a-50beac4f6f90",
  "type": "dialogue",
  "props": { "disabled": false, "characterId": "b8e3efe5-…" },
  "content": [
    { "type": "text", "text": "台词正文。", "styles": {} }
  ]
}
字段JSON 类型生成时必填默认值 / 缺省行为约束
idstring否BlockNote 编辑器加载该片段时可自动生成新建 Block 可省略;修改已有 Block 时保留。自行提供时保证唯一;片段跳转不引用 Block id
typestring是无可供生成器依赖的默认值大小写敏感,使用下文指令全参考中的类型;不要用 text、say、jump 替代指令类型
propsobject是各指令有不同参数默认值无参数也写 {};不是数组或 JSON 字符串。仅写该类型支持的属性
props.disabledboolean否false所有内置剧本指令共用;必须放在 props 内,不是 Block 顶层
contentInlineContent[]有正文时填写无正文可省略;空正文可写 []正文类型为 dialogue、narration、storyParagraph、comment、floatingText;生成时统一使用下节的文本数组
childrenBlock[]否普通指令不需要BlockNote 保存结果可能带 children: [];普通剧情用片段的 blocks 顺序表达,不要把条件或分支剧情嵌在这里
这里的“生成时必填”是生成可用剧本的约定,不代表读取器会在缺字段时自动报错。原始数据接口为兼容旧工程和扩展允许更宽的形态,不应据此省略 type 或猜测新字段。 最小无正文 Block(等待默认的 1000 毫秒):
{ "type": "wait", "props": {} }
显式写出默认参数的等价版本:
{
  "type": "wait",
  "props": { "disabled": false, "duration": 1000, "waitForInput": false }
}

参数存储的三条约定

编辑器底层只能在 props 里保存标量(字符串、数字、布尔),因此磁盘 JSON 有几个乍看奇怪、实则一致的约定:
  1. 不少布尔与数值以字符串保存。例如 sound 的 "loop": "true"、"volume": "80",scene 的 "waitForComplete": "false"。每个字段的实际存储类型以指令参考页的标注为准,不要自行改成真布尔/真数字。
  2. 复杂结构一律是「JSON 字符串」,即把整个 JSON 数组或对象序列化成一个字符串再存入 props。涉及的字段:branch.choices、if.conditions、stageAnimation.clipJson、callExtensionFunction.paramsJson、particle.optionsJson、camera.objectTargetsJson。
  3. 区分 schema 默认值和可执行所需值。下文默认列主要表示编辑器 propSchema 的初始值;例如 characterId: "" 只是尚未选择角色,不表示空 id 能显示角色。生成时仍需填齐功能必需参数。编辑器加载 Block 时可补默认参数,但读取章节文件本身不等于遍历并补全所有 Block;若绕过编辑器直接交给脚本工具或编译器,应显式写出影响行为的参数。
省略字段、空字符串、null 不是一回事。只有字段表明确说明时,"" 才表示“使用默认”或“清除”;不要给缺省字段批量填 null。JSON 不允许注释、尾逗号、undefined 或省略号。

正文的结构

正文是一个内联片段数组,最常用的形态:
{ "content": [ { "type": "text", "text": "这是一句话。", "styles": {} } ] }
上面只是 content 字段示意,不是完整 Block。每个纯文本内联项的约定如下:
字段JSON 类型生成时必填约束
typestring是固定 "text";这是内联项类型,不是 Block 类型
textstring是正文;空字符串表示空文本,换行在 JSON 中写 \n
stylesobject是无格式写 {};加粗可写 {"bold":true},文字颜色可写 {"textColor":"#ff0000"}
一条正文可以拆成多段不同样式的 text 片段。纯文本生成统一使用上面的数组结构,不要把台词放进 props.text、Block 顶层 text,也不要把整个 content 数组序列化成字符串。

引用规则

这是 AI 生成剧本最容易出错的地方:所有 id 引用都必须指向工程里真实存在的实体,不能凭空编造。
引用格式来源
角色 characterIdUUIDcharacters.json 里 characters[].id
场景 sceneIdUUIDscenes.json 里 scenes[].id
音频 soundIdUUID资源库中音频素材的 id
片段 fragmentIdfrag-…同一章节内 fragments[].id
素材 uri相对路径assets/ 下的路径,如 bgm/主题曲.mp3、video/intro.mp4
表情 expression / 皮肤 skin名字字符串该角色在 characters.json 里配置过的表情名 / 皮肤名
变量的 key 有三种命名空间:
变量种类key 写法例子
全局 / 系统变量裸名字alice_affection
角色属性变量角色UUID.属性名b8e3efe5-….好感度
扩展存档变量扩展id.键名avg.official.affection.total
其他通用格式:
  • 坐标与尺寸:写成 "(x,y)" / "(宽,高)" 的字符串,支持像素、百分比和 center / left / right / top / bottom 关键字,如 "(center,center)"、"(50%,200)"。
  • 颜色:CSS 色值字符串,如 "#000000"。
  • 站位 / 距离:position 内置 left / center-left / center / center-right / right,distance 内置 far / middle / near;空字符串表示用工程默认,也可以填工程里自定义预设的 id。

三个复杂结构详解

分支的选项列表

branch 指令的 props.choices 是一个 JSON 字符串,反序列化后是选项数组。选项有两种模式:
[
  { "mode": "jump", "text": "去图书馆", "fragmentId": "frag-3" },
  {
    "mode": "vars",
    "text": "回家休息",
    "varOps": [
      {
        "key": "b8e3efe5-….好感度",
        "op": "+=",
        "aKind": "lit",
        "aLit": "5",
        "bKind": "none",
        "binOp": "+"
      }
    ]
  }
]
字段JSON 类型生成时必填默认值 / 约束
modestring是"jump" 或 "vars";旧数据缺省可兼容为 jump,新生成时显式填写
textstring是无可用默认文案;填写玩家看到的选项文字
fragmentIdstringjump 模式必填非空时指向同章非 main 片段;"" 表示选中后直接继续当前片段
varOpsobject[]vars 模式必填每项与下文 setver 运算字段同构;[] 表示不修改变量。这里是数组,整个 choices 才序列化成字符串
visibleIfstring否省略或空字符串表示不附加显示条件;可填写变量表达式,为真才显示。编辑器也会保存结构化条件的 JSON 字符串,修改现有数据时保留其格式
isDefaultboolean否缺省不标记默认项;true 标为预览快进的默认选项,全组最多一个。不要写成 "true"
新建空白分支的 choices 默认值是字符串 "[]",但这不构成有意义的玩家选项。生成可用分支时至少提供一个有文字的选项。 写入 props 时记得把整个数组序列化成字符串:
{
  "choices":
    "[{\"mode\":\"jump\",\"text\":\"去图书馆\",\"fragmentId\":\"f3\"}]"
}

条件的结构

if 指令的 props.conditions 也是 JSON 字符串,反序列化后是条件数组,多条之间用 props.logicOp(and / or)连接:
[
  {
    "left": "alice_affection",
    "op": ">=",
    "rightKind": "literal",
    "rightLiteral": "50"
  },
  {
    "left": "route_flag",
    "op": "==",
    "rightKind": "variable",
    "rightRef": "target_route"
  }
]
字段JSON 类型生成时必填默认值 / 约束
sourceKindstring否缺省为 "variable";扩展方法条件为 "extension-method"
leftstring变量条件必填变量 key;编辑器占位值 "" 不是有效变量引用。custom 或扩展方法条件可写 ""
opstring是新建条件初值 "==";可用 == != > >= < <= contains notContains startsWith endsWith isEmpty isNotEmpty exists notExists custom
rightKindstring是新建条件初值 "literal";"literal" 用字面量,"variable" 用变量
rightLiteralstring字面量比较 / custom 时必填新建初值 "";数字如 "50",布尔如 "true",字符串如 "你好";custom 时是表达式文本
rightRefstring变量比较时必填无有效默认引用;填另一个真实变量 key
extensionMethodstring扩展方法条件必填真实方法全局 id,不能编造
extensionParamsobject按方法声明使用该方法声明的参数,值为 {"kind":"lit","value":5} 或 {"kind":"var","ref":"score"};此处是真对象
extensionReturnTypestring否编辑器记录的返回类型,运行时以扩展声明为准;没有声明时不要猜测
一元算子(isEmpty / isNotEmpty / exists / notExists)不需要右值。条件为真跳 thenFragmentId(必填),为假跳 elseFragmentId(可空,空则继续当前片段)。

变量赋值的运算字段

setver 把「A 运算」拆成了几个标量字段,branch 选项里的 varOps 与它同构:
字段JSON 类型默认值约束
keystring""必须填写已声明的目标变量 key;空值不是可执行默认
opstring"="= += -= *= /=;生成时显式填写所需操作
aKindstring"lit"lit(字面量)或 var(变量)
aLitstring""aKind=lit 时提供有效字面量
aVarstring""aKind=var 时填写真实变量 key
bKindstring"none"none / lit / var
bLitstring""bKind=lit 时提供有效字面量
bVarstring""bKind=var 时填写真实变量 key
binOpstring"+"双操作数之间的 + - * /
两条组合规则:op 不是 = 时 bKind 必须是 none(即 好感度 += 5 这种形态);要用双操作数(金钱 = 基础 + 奖金)时 op 必须是 =。字面量写法:true、123、"你好"(字符串带引号)。

指令全参考

以下覆盖当前 43 种内置剧本 Block 类型,其中 animateSprite、hideStageMask 仅供读取旧工程,41 种可用于新剧本。各节列出用途与参数;扩展自定义 Block 还需要对应扩展的 schema,不能自行编造。图形界面用法见各节「手册」链接。

文本与角色

对白、旁白、立绘与文字样式 · 9 种

场景与演出

场景、镜头、粒子与浮动文字 · 12 种

音视频

音乐、音效与视频 · 4 种

逻辑流程

分支、条件、变量与章节流转 · 10 种

界面与扩展

消息框、链接、Steam 与扩展方法 · 7 种

注释

只给编辑者看的备注 · 1 种
四条阅读约定
  1. 所有指令的 props 都支持 "disabled": true(这条指令不执行),字段表里不再重复。
  2. 类型列就是磁盘存储类型:标 "true"/"false" 的是字符串布尔,标 boolean 的才是真布尔;标「JSON 字符串」的字段要把整个结构序列化成字符串存入。
  3. 默认值与功能必填值不同:默认 "" 的资源引用仍需填写真实 id。精简示例面向编辑器加载;自动化直编时显式填写关键参数。
  4. 每节末尾「生成时勿填」列出的字段由编辑器自动维护,AI 生成剧本时不要输出。

文本与角色

写故事最常用的一组:说话、叙述,以及立绘和文字样式的控制。

对白

type: "dialogue" 角色说一句话,一句一个 Block,正文放 content。图形界面用法见手册:对白。
{
  "type": "dialogue",
  "props": {
    "characterId": "<角色UUID>",
    "characterName": "小雪",
    "expression": "微笑",
    "position": "center"
  },
  "content": [
    { "type": "text", "text": "今天想去哪里?", "styles": {} }
  ]
}
字段类型必填默认说明
characterIdUUID✅""说话角色,引用 characters.json
characterNamestring""角色显示名(冗余字段,与角色同名即可)
nameVariantIdstring""角色的名字变体 id,空 = 主名称
expressionstring""该角色配置过的表情名
skinstring""立绘皮肤名,空 = 自动
distancestring""far / middle / near 或自定义距离预设 id,空 = 默认
positionstring""left / center-left / center / center-right / right 或自定义站位预设 id
showCharacterbooleantrue说话时是否同时显示立绘
dialoguePortraitOnlybooleanfalse只显示对话框头像,不上舞台立绘
keepCharacterbooleantrue这组对白结束后是否保留立绘
keepDialoguebooleantrue结束后是否保留对话框
两个常见的 AI 生成坏习惯,请避免:
  1. 不要在对白前多加「角色登场」。对白自带立绘显示(showCharacter 默认 true),说话时角色会自动登场;前面再加一个 showCharacter 指令就是重复调用。只有角色不说话就要先站上舞台时,才单独使用「角色登场」。
  2. 对话收尾要放下对话框。一段对话结束、后面不再有对白时(尤其接镜头动画、场景切换等演出),把最后一句 dialogue 或 narration 的 keepDialogue 设为 false,对话框会自动隐藏,演出画面才干净。
生成时勿填:isFirst、isLast、prevExpression、prevNameVariantId、voiceHash、entryMotion* / exitMotion* 系列。

旁白

type: "narration" 无角色的叙述文字,显示在对话框里。图形界面用法见手册:旁白。
{
  "type": "narration",
  "props": {},
  "content": [
    {
      "type": "text",
      "text": "放学后的教室,只剩下我们两个人。",
      "styles": {}
    }
  ]
}
字段类型必填默认说明
keepDialoguebooleantrue结束后是否保留对话框
生成时勿填:voiceHash。

段落

type: "storyParagraph" 整屏长文(小说式演出),相邻的段落 Block 会合并成一屏。见手册:段落。
字段类型必填默认说明
speednumber0文字速度(字/秒),0 = 跟随全局设置
生成时勿填:isFirst。

角色登场

type: "showCharacter" 让角色立绘出现在舞台上(不说话)。注意:对白会自动显示立绘,本指令只用于角色不说话就登场的场合,不要作为对白的前置步骤。见手册:角色。
{
  "type": "showCharacter",
  "props": {
    "characterId": "<角色UUID>",
    "expression": "微笑",
    "position": "left"
  }
}
字段类型必填默认说明
characterIdUUID✅""角色引用
characterNamestring""显示名冗余字段
expressionstring""空 = 角色的第一个表情
skinstring""立绘皮肤
distance / positionstring""同「对白」
cameraBoundbooleanfalse立绘是否参与镜头位移 / 震动 / 景深
cameraDistancenumber1镜头深度距离,越小越靠近镜头
生成时勿填:animated 与 motion* 系列。

更新立绘

type: "updateCharacter" 修改已在场角色的表情、皮肤或站位。见手册:更新立绘。
字段类型必填默认说明
characterIdUUID✅""角色引用
characterNamestring""显示名冗余字段
expression / skin / distance / positionstring""同「对白」,空 = 不变
placementTransitionEnabledbooleantrue换位时是否播放平移动画
placementTransitionDurationnumber350换位动画时长(毫秒)
placementTransitionEasingstring"outCubic"linear / inOutQuad / outCubic
placementTransitionBlockingbooleanfalse是否阻塞后续指令

移除立绘

type: "removeCharacter" 见手册:移除立绘。
字段类型必填默认说明
characterIdUUID✅""要移除的角色
characterNamestring""显示名冗余字段
生成时勿填:motion* 系列。

设置对话参数

type: "switchDialogueStyle" 切换对话框样式或微调打字机参数,数值参数以 -1 表示「不覆盖」。见手册:设置对话参数。
字段类型必填默认说明
sourcestring""样式来源:preset / user / system / extension,空 = 只改参数不换样式
targetIdstring""对应来源下的样式 id
extensionIdstring""source 为 extension 时的扩展 id
textSpeednumber-1每字间隔毫秒(0–200)
charFadeInnumber-1单字淡入时长(0–300)
waitForIconDelaynumber-1等待图标出现延迟(0–2000)
showWaitForIconstring""三态:""(不变)/ "true" / "false"

设置段落参数

type: "switchParagraphStyle" 切换段落样式与文字浮现效果,数值参数以 -1 表示「不覆盖」。见手册:设置段落参数。
字段类型必填默认说明
sourcestring""preset / user / extension,空 = 只改参数
targetId / extensionIdstring""同上
textSpeednumber-1每字间隔毫秒
charFadeInnumber-1单字淡入时长
revealEffectstring""浮现效果:smooth-rise / classic / instant / smooth-drop / slide-left / slide-right / pop / flip / swing / blur,空 = 不变
revealDistancenumber-1浮现位移距离(0–48 像素)
revealScalenumber-1起始缩放(30–100,百分比)
revealRotationnumber-1起始旋转角度(0–180)
revealBlurnumber-1起始模糊(0–12 像素)
readModestring""已读段落:dim(变暗)/ keep(保留)/ hide(隐藏),空 = 不变
historyLimitnumber-1保留的历史段落数,0 = 不限

设置立绘发言状态

type: "portraitStyleRule" 一条「规则」指令:设定之后所有对白的立绘进退场动效、发言高亮和空间聚焦。字段较多,按组列出,全部为标量直存。见手册:设置立绘发言状态。 总开关与版本
字段类型默认说明
enabledbooleantrue规则总开关
portraitMotionSemanticsVersionnumber0新建规则写 2;0 是旧工程兼容语义
进场动效 entryMotion* 与退场动效 exitMotion*(两组字段同构,仅前缀不同)
字段(以 entry 为例)类型默认说明
entryMotionEnabledbooleantrue是否启用
entryMotionPresetstring"classic"classic / fade / slide / rise / pop / swoop / drop / zoom / float / wipe / dissolve / none
entryMotionDurationnumber300时长(毫秒)
entryMotionIntensitynumber1强度,建议 0.25–2
entryMotionDirectionstring"auto"auto / left / right / up / down
entryMotionTimingstring"preset"preset / smooth / snappy / bounce / linear
entryMotionFadeEnabledbooleantrue是否叠加淡入淡出
entryMotionDistanceModestring"offset"offset(固定位移)/ offscreen(从屏幕外)
entryMotionEdgeSoftnessnumber-1wipe / dissolve 边缘柔化(0–0.25),-1 = 按预设默认
entryMotionGrainSizenumber-1dissolve 颗粒大小(2–64),-1 = 按预设默认
entryMotionWaitbooleanentry false / exit true是否等动效播完再继续
发言状态
字段类型默认说明
speakingStateEnabledbooleantrue发言高亮总开关
othersStatestring"inactive"其他角色的状态:listening / inactive
narrationStatestring"listening"旁白时全体状态:listening / inactive / keep
transitionEnabledbooleantrue状态切换是否渐变
transitionDurationnumber180渐变时长(毫秒)
transitionEasingstring"outQuad"linear / outQuad / inOutQuad / outCubic / outBack
transitionBlockingbooleanfalse渐变是否阻塞下一句台词
三态视觉参数 —— speaking / listening / inactive 三组前缀 × 六个参数(Scale / Brightness / Saturation / Contrast / Blur / Alpha),共 18 个 number 字段,如 speakingScale、inactiveBrightness。默认值:
前缀ScaleBrightnessSaturationContrastBlurAlpha
speaking1.041.081101
listening10.880.82101
inactive10.80.42101
空间聚焦 focusMotion*(发言角色向镜头前聚焦的电影感效果)
字段类型默认说明
focusMotionEnabledbooleanfalse总开关
focusMotionStrengthnumber0.16聚焦位移强度
focusMotionDistancenumber0.75发言者的镜头距离
focusMotionDefocusDistancenumber1非发言者的镜头距离
focusMotionCameraZoomnumber1发言时镜头缩放
focusMotionNarrationCamerastring"keep"旁白时镜头:center / keep
focusMotionNarrationCameraZoomnumber1旁白时镜头缩放
focusMotionScalenumber1.02发言者额外缩放
focusMotionBackgroundModestring"fixed"背景:fixed / follow
focusMotionCharacterZoomModestring"fixed"立绘缩放:fixed / follow
focusMotionCenterModestring"position"聚焦中心:position / anchor
focusMotionCenterPositionIdstring""中心站位 id
focusMotionEntryModestring"direct"入场衔接:direct / afterEnter
focusMotionWaitPreviousExitbooleanfalse是否等上一位退场
focusMotionTransitionEnabledbooleantrue聚焦切换是否渐变
focusMotionDurationnumber180渐变时长(毫秒)
focusMotionEasingstring"outQuad"同发言状态的枚举
focusMotionBlockingbooleanfalse是否阻塞
生成时勿填:placementTransition* 四个字段(换位动画已迁移到「更新立绘」)。

场景与演出

背景、镜头与视觉演出。

场景切换

type: "scene" 切换背景场景,带 22 种转场效果。见手册:场景。
{
  "type": "scene",
  "props": {
    "sceneId": "<场景UUID>",
    "sceneName": "教室",
    "transitionMode": "crossfade",
    "transitionDuration": "500"
  }
}
核心字段
字段类型必填默认说明
sceneIdUUID✅""场景引用,来自 scenes.json
sceneNamestring""显示名冗余字段
transitionModestring"cover"转场方式,见下表
transitionDurationstring"500"转场时长(毫秒)
waitForComplete"true"/"false""false"是否等转场播完再继续
resetCamera"true"/"false""false"切换时是否复位镜头
displayTypestring"cover"铺放方式:cover / contain / by_width / by_height / stretch / center
positionstring"(center,center)"位置,"(x,y)" 格式
anchorstring"center"锚点九宫格:top-left / top-center / top-right / center-left / center / center-right / bottom-left / bottom-center / bottom-right
sizestring"""(宽,高)",空 = 按 displayType
autoAddToGallery"true"/"false""true"展示成功后自动加入鉴赏(CG 收集)
uri / galleryMethodTargetstring由资源系统 / 默认壳维护,一般不用填
22 种转场方式(transitionMode)
值效果值效果
cover覆盖(默认)rule规则图(配 transitionRuleUri)
crossfade交叉淡化radial-wipe放射扫除
fade-to-black黑场过渡barn-door对开门
fade-to-white白场过渡diagonal-wipe斜切
cut瞬切zoom-fade缩放淡化
wipe方向擦除blur-dissolve模糊溶解
slide滑入mosaic马赛克
blinds百叶窗glitch故障闪烁
rotate旋转缩放page-turn翻页
iris圆形展开checkerboard棋盘格
pixel-dissolve像素溶解random-dissolve随机溶解
转场微调参数(只在对应模式下生效)
字段默认说明
transitionDirection""方向。擦除/滑入:left-to-right / right-to-left / top-to-bottom / bottom-to-top;百叶窗/对开门:vertical / horizontal;旋转/放射:clockwise / counterclockwise;斜切:top-left-to-bottom-right 等四角方向。空 = 各模式默认
transitionStrips"12"百叶窗叶片数(2–64)
transitionRuleUri""rule 模式的灰度规则图路径,如 transitions/ink-wash.png
transitionCenterX / transitionCenterY"50"转场中心(百分比 0–100),用于 iris / radial-wipe / barn-door
transitionSoftness""边缘柔化(0–20%);空时 rule 默认 5.5
transitionZoomScale"1.14"zoom-fade 缩放(1–2)
transitionBlurStrength"16"blur-dissolve 模糊(0–32)
transitionMosaicSize"52"mosaic 块大小(2–128)
transitionGlitchStrength / ColorShift / Scanlines"100" / "4.5" / "17"glitch 专用
transitionPagePerspective / transitionPageShadow"50" / "38"page-turn 专用(百分比)
mouseParallaxEnabled"false"是否让当前场景跟随鼠标移动
mouseParallaxAmplitude"4"鼠标位于画布边缘时的最大移动幅度(画布百分比,0–100)
mouseParallaxEdgeEase"0"接近画布边缘时的跟随减速程度(0–100);0 为线性跟随
mouseParallaxReturnOnLeave"true"鼠标移出游戏画布时是否平滑回到中心
mouseParallaxScaleMode"auto"auto 根据幅度和最近图层距离防露边;custom 使用指定倍率
mouseParallaxScale"1.08"自定义缩放倍率(1–5),仅 custom 模式生效

销毁场景

type: "destroyScene" 见手册:销毁场景。
字段类型必填默认说明
sceneIdstring✅"all"场景 UUID;"all" = 销毁全部
sceneNamestring""显示名冗余字段
animated"true"/"false""true"是否播放淡出
waitForComplete"true"/"false""false"是否等待完成

帷幕

type: "curtain" 拉上 / 拉开一层纯色幕布,常用于转场和黑屏演出。见手册:帷幕。
{
  "type": "curtain",
  "props": { "op": "close", "duration": "800" }
}
字段类型必填默认说明
opstring✅"close"close(拉上)/ open(拉开)
durationstring"1000"动画时长(毫秒)
colorstring"#000000"幕布颜色(CSS 色值)
modestring"full-screen"full-screen(全屏)/ letterbox(上下黑边)/ pillarbox(左右黑边)/ windowbox(四边)
curtainSizestring"100"黑边占比(0–100)
生成时勿填:effect(旧数据兼容)。

镜头特效

type: "camera" 控制镜头位移、缩放、对焦、震动与全部滤镜。见手册:镜头特效。
所有数值字段都是字符串,空字符串 = 该参数保持不变。 只填想改的参数即可,比如推近镜头只需要 zoom 和 duration 两个字段。
{
  "type": "camera",
  "props": {
    "zoom": "1.4",
    "offsetY": "-60",
    "colorToneMode": "sepia",
    "colorToneIntensity": "0.6",
    "duration": "800",
    "easing": "easeInOut"
  }
}
基础与补间
字段默认说明
offsetX / offsetY""镜头位移(像素),建议 ±300 / ±200
zoom""缩放,建议 0.8–2.5
focalDistance""对焦距离(0–1)
blurStrength""景深模糊强度
duration"0"补间时长(毫秒),"0" = 立即生效
easing"linear"linear / easeInOut
waitForComplete"true"是否等补间播完
targets"scene,characters"作用范围:场景、立绘或两者
tweenFields内置默认逗号分隔的字段名,只有列出的字段参与补间;一般省略
objectTargetsJson""JSON 字符串,精确指定作用对象;空 = 按 targets 全局范围
震动
字段默认说明
shakeAmplitude""振幅(4–30 像素),非空即触发震动
shakeFrequency""频率(4–20 Hz)
shakeAmplitudeRandomness / shakeFrequencyRandomness"0"随机度(0–100)
shakeFalloff"linear"衰减:linear / expo
shakeAxis"both"方向:both / x / y
色彩与基础滤镜(默认均为 "" = 不变)
字段说明
colorToneMode色调:none / grayscale(黑白)/ sepia(怀旧),默认 "none"
colorToneIntensity色调强度(0–1)
colorExposure曝光(-2–2)
colorBrightness / colorContrast亮度 / 对比度(-1–1)
colorSaturation饱和度(0–2)
colorTemperature色温(-1–1)
lutPreset / lutIntensityLUT 调色预设与强度
distortionStrength镜头畸变(-1–1)
vignetteIntensity / vignetteSize暗角强度 / 范围(0–1)
blurAmount全屏模糊(0–20)
sharpenStrength锐化(-1–1)
bloomIntensity泛光
chromaticAberration色差(-20–20)
pixelateSize像素化块大小(1–64)
glitchIntensity故障艺术强度
crtIntensityCRT 扫描线
oldFilmIntensity老电影颗粒
shockIntensity冲击波
体积光 Godray
字段说明
godrayIntensity强度,非空即启用
godrayAngle / godrayGain / godrayLacunarity / godraySpeed角度 / 增益 / 细节 / 流动速度
godrayParallel光源模式:"" / true(平行光)/ false(点光)/ spotlight(聚光)
godrayCenterX / godrayCenterY光源位置
godrayConeAngle / godrayConeSoftness / godrayDistance聚光锥角 / 边缘柔化 / 距离
方向模糊
字段说明
radialBlurStrength / radialBlurCenterX / radialBlurCenterY放射模糊:强度与中心
motionBlurStrength / motionBlurAngle运动模糊:强度与角度
zoomBlurStrength / zoomBlurCenterX / zoomBlurCenterY缩放模糊:强度与中心
氛围叠加
效果字段
漏光lightLeakIntensity / lightLeakAngle
镜头光斑lensFlareIntensity / lensFlareCenterX / lensFlareCenterY
胶片颗粒filmGrainIntensity / filmGrainSize
热浪heatHazeIntensity / heatHazeSpeed / heatHazeScale
水波waterRippleIntensity / waterRippleFrequency / waterRippleSpeed / waterRippleCenterX / waterRippleCenterY
玻璃碎裂mirrorShatterIntensity(碎裂程度)/ mirrorShatterCenterX / mirrorShatterCenterY(撞击位置)
雾fogIntensity / fogSpeed / fogScale
VHS 录像带vhsIntensity / vhsJitter / vhsNoise
半调网点halftoneIntensity / halftoneScale / halftoneAngle
抖动色阶ditherIntensity / ditherLevels
描边outlineIntensity / outlineThickness
速度线
字段说明
speedLinesIntensity强度,非空即启用
speedLinesModeradial(放射,默认)/ directional(定向)
speedLinesDensity / speedLinesAngle / speedLinesSpeed密度 / 角度 / 速度
speedLinesFlicker / speedLinesIrregularity闪烁 / 不规则度
speedLinesLength / speedLinesThickness / speedLinesThicknessVariation长度 / 粗细 / 粗细变化
speedLinesTone / speedLinesFocus明暗 / 聚焦范围
speedLinesCenterX / speedLinesCenterY中心位置
泼墨 / 烟雾 / 眼睑
效果字段
泼墨inkSplashIntensity、inkSplashVariant(cluster / burst / slash,默认 "cluster")、inkSplashScale、inkSplashRotation、inkSplashTone、inkSplashCenterX / inkSplashCenterY
烟雾smokeOverlayIntensity、smokeOverlayVariant(left / right / full,默认 "full")、smokeOverlayStyle(warm / soft / dark,默认 "warm")、smokeOverlayTone、smokeOverlayScale、smokeOverlaySpeed
眼睑(睁眼/闭眼演出)eyelidOpenness(睁开程度)、eyelidWidth、eyelidCurvature、eyelidSoftness、eyelidCenterX / eyelidCenterY;仅作用于场景层
生成时勿填:shakeDuration(旧兼容,震动时长走顶部 duration)、presetId、targetSelectionPending。

复位镜头

type: "resetCamera" 清除所有镜头位移与滤镜,恢复默认视角。见手册:复位镜头。
字段类型必填默认说明
resetModestring"instant"instant(立即)/ animated(动画过渡)
durationstring"500"animated 时的过渡时长(毫秒)
easingstring"easeInOut"linear / easeInOut
waitForComplete"true"/"false""true"是否等待完成

镜头动画

type: "stageAnimation" 多轨时间轴演出,在 Studio 的演出设计视图编辑。AI 生成剧本时一般只放一个占位,由创作者在 Studio 里编排。见手册:镜头动画。
字段类型必填默认说明
namestring"镜头段"演出段名称
clipJsonJSON 字符串空轨道轨道数据,默认 {"version":1,"duration":3000,"tracks":[],"events":[]}
loopstring"0"循环次数,"0" = 不循环
playbackRatestring"1"播放速率
waitForComplete"true"/"false""true"是否等待播完

蒙层

type: "stageMask" 显示、更新或移除舞台蒙层。覆盖蒙层用于聚光、挖洞和氛围效果;对象裁剪用于裁剪场景与立绘。见手册:蒙层。
{
  "type": "stageMask",
  "props": {
    "action": "show",
    "maskId": "spotlight",
    "mode": "overlay",
    "plane": "bottom",
    "shape": "ellipse",
    "visibility": "inside",
    "centerX": 50,
    "centerY": 45,
    "width": 36,
    "height": 60,
    "feather": 24,
    "opacity": 85,
    "color": "#000000",
    "enterDuration": 1000
  }
}
操作与目标
字段类型必填默认说明
actionstring"show"show(显示或更新)/ remove(移除)
maskIdstring"mask"稳定 ID;show 使用相同 ID 会更新已有蒙层;remove 时留空表示移除当前剧情创建的全部蒙层
modestring"overlay"overlay(覆盖蒙层)/ clip(对象裁剪)
planestring"bottom"覆盖层级:behind-scene / bottom / top / topmost;仅 overlay 使用
scopestring"stage"裁剪范围:scene / characters / stage / selected;仅 clip 使用
targetsJsonJSON 字符串""selected 的目标数组;元素为场景、场景图层或角色引用
形状与变换
字段类型必填默认说明
shapestring"rect"rect / rounded-rect / ellipse / image
imagestring""image 形状使用的 PNG / WebP 素材路径
imageChannelstring"alpha"alpha(透明度)/ luma(亮度)
imageFitstring"stretch"stretch / cover / contain
centerX / centerYnumber50 / 50中心位置,占设计画布百分比
width / heightnumber50 / 50宽高,占设计画布百分比
rotationnumber0旋转角度
radiusnumber24圆角矩形的圆角半径(像素)
visibilitystring"inside"inside(保留形状内部)/ outside(保留形状外部)
coordinateSpacestring"screen"坐标空间;当前统一使用 screen,target 仅为旧数据兼容
feathernumber0边缘羽化(像素)
覆盖填充与效果 以下字段只影响 overlay;clip 只使用上面的形状和羽化设置。
字段类型必填默认说明
opacitynumber100覆盖强度百分比
colorstring"#000000"纯色填充颜色
fillModestring"solid"solid / gradient / texture
gradientStart / gradientEndstring"#000000" / "#243247"渐变起始色 / 结束色
gradientDirectionnumber0渐变方向角度;0 为上到下,90 为左到右
texturestring""纹理素材路径
textureFitstring"cover"cover / contain / tile
textureBlendstring"normal"normal / multiply / screen / overlay
textureScale / textureOpacitynumber100 / 100纹理缩放 / 透明度百分比
blurEnabled / blurAmountboolean / numberfalse / 8启用模糊 / 模糊强度(像素)
vignetteEnabled / vignetteAmount / vignetteSizeboolean / number / numberfalse / 35 / 55启用暗角 / 强度 / 中心范围
noiseEnabled / noiseAmount / noiseSizeboolean / number / numberfalse / 12 / 45启用噪点 / 强度 / 颗粒尺寸
colorAdjustmentEnabledbooleanfalse是否启用调色
colorHue / colorSaturation / colorBrightnessnumber0 / 100 / 100色相角度 / 饱和度 / 亮度
enterDuration / exitDurationnumber1000 / 1000淡入 / 淡出时长(毫秒);范围 0~60000

隐藏蒙层(遗留)

type: "hideStageMask"
此类型只用于读取旧工程。新剧本请使用 stageMask,把 action 设为 remove。
字段类型必填默认说明
maskIdstring""要移除的蒙层 ID;留空表示移除当前剧情创建的全部蒙层
exitDurationnumber1000淡出时长(毫秒),0 表示立即移除

粒子效果

type: "particle" 下雪、下雨、萤火虫等全屏粒子。见手册:粒子效果。
{
  "type": "particle",
  "props": { "mode": "show", "preset": "LIGHT_SNOW" }
}
字段类型必填默认说明
modestring✅"show"show(显示)/ hide(销毁)
effectIdstring""粒子实例 id;show 时定义、hide 时引用,hide 留空 = 销毁全部
presetstring"LIGHT_SNOW"LIGHT_SNOW / MODERATE_SNOW / HEAVY_SNOW(小/中/大雪)、LIGHT_RAIN / MODERATE_RAIN / HEAVY_RAIN(小/中/大雨)、FIREFLY(萤火虫)、FALLEN_LEAVES(落叶)、custom
textureUristring""自定义粒子贴图路径
optionsJsonJSON 字符串""完整粒子参数,空 = 用预设
fadeInDuration / fadeOutDurationstring"500"淡入 / 淡出时长(毫秒)

浮动文字

type: "floatingText" 在画面任意位置显示一段可动画的文字(标题、地点提示、内心独白等)。正文放 content,支持 [color=red]…[/color]、[b]、[i]、[size=32] 样式标记。见手册:浮动文字。
{
  "type": "floatingText",
  "props": {
    "position": "(center,20%)",
    "anchor": "top-center",
    "fontSize": "42",
    "animIn": "fade,slide"
  },
  "content": [
    { "type": "text", "text": "——三年后。", "styles": {} }
  ]
}
字段类型必填默认说明
floatingTextIdstring""实例 id,空 = 自动生成;常驻文字需自取 id 供后续隐藏
blocking"true"/"false""true"是否阻塞剧情推进
recordHistory"true"/"false""false"是否进入历史记录
positionstring"(0,0)"位置 "(x,y)"
anchorstring"top-left"锚点九宫格(同「场景切换」)
sizestring"""(宽,高)",空 = 自适应
colorstring"#ffffff"文字颜色
fontFamily / fontSize / lineHeight / letterSpacing / textShadowstring""文字样式,空 = 默认
fontWeight / fontStylestring"normal"字重 / 斜体
textAlignstring"left"对齐
durationstring"2000"显示时长(毫秒)
infinite"true"/"false""false""true" = 不自动消失,需「隐藏浮动文字」手动隐藏
animIn / animOutstring"fade"入 / 出场动画,可逗号叠加:fade / slide / scale / blur
inDuration / outDurationstring"300"入 / 出场动画时长
slideFromstring"top"slide 方向
slideDistancestring"40"slide 距离(像素)
scaleFrom / scaleTostring"0.8"scale 起止缩放
blurRadiusstring"8"blur 动画模糊半径

隐藏浮动文字

type: "hideFloatingText"
字段类型必填默认说明
floatingTextIdstring""要隐藏的实例 id,空 = 隐藏全部

精灵动画(遗留)

type: "animateSprite"
遗留类型,仅用于读取旧工程,AI 与新剧本都不要使用。移动镜头请用「镜头特效 camera」,编排演出请用「镜头动画 stageAnimation」。

音视频

播放声音

type: "sound" 见手册:声音。
{
  "type": "sound",
  "props": {
    "soundType": "BGM",
    "soundId": "<音频UUID>",
    "uri": "bgm/日常.mp3",
    "loop": "true",
    "volume": "80"
  }
}
字段类型必填默认说明
soundTypestring✅"BGM"BGM(背景音乐)/ SE(音效)/ VOCAL(语音)
soundIdUUID✅""音频资源引用
uristring""资源相对路径,如 bgm/主题曲.mp3
volumestring"100"音量(0–100)
loop"true"/"false""false"是否循环(BGM 通常填 "true")
fadeDurationstring""淡入时长(毫秒),空 = 立即

停止声音

type: "stopSound" 见手册:停止声音。
字段类型必填默认说明
soundTypestring✅"BGM"要停止的声音类型
soundIdstring""指定音轨 id,空 = 停止该类型的默认音轨
fadeDurationstring""淡出时长(毫秒),空 = 立即

播放视频

type: "video" 见手册:视频。
字段类型必填默认说明
uristring✅""视频路径,如 video/intro.mp4
videoIdstring"video"视频实例 id
loop"true"/"false""true"是否循环
muted"true"/"false""true"是否静音
alphastring"100"不透明度(0–100)
waitForFinished"true"/"false""false"是否等播完再继续
modestring"normal"normal / mixed(叠加发光混合,适合特效视频)

停止视频

type: "stopVideo"
字段类型必填默认说明
videoIdstring""要停止的实例 id,空 = 停止全部
fadeOutDurationstring""淡出时长(毫秒)

逻辑流程

分支、条件、变量与章节流转——剧本的骨架。

选项分支

type: "branch" 向玩家展示选项。choices 的内部结构详见上文分支的选项列表。见手册:分支。
{
  "type": "branch",
  "props": {
    "title": "去哪里",
    "choices":
      "[{\"mode\":\"jump\",\"text\":\"出发\",\"fragmentId\":\"f3\"}]"
  }
}
字段类型必填默认说明
choicesJSON 字符串✅"[]"选项数组
titlestring""编辑器内的分支标题,不显示给玩家
branchIdUUID""叙事地图用的稳定身份,可省略(自动补)

条件

type: "if" 按变量条件跳转片段。conditions 的内部结构详见上文条件的结构。见手册:条件。
字段类型必填默认说明
conditionsJSON 字符串✅""条件数组
logicOpstring"and"多条件连接:and / or
thenFragmentIdstring✅""条件为真跳转的片段(同章节、非 main)
elseFragmentIdstring""条件为假跳转的片段,空 = 继续当前片段
生成时勿填:expression(由编辑器从 conditions 派生)。

变量赋值

type: "setver" 修改变量的值。字段与组合规则详见上文变量赋值的运算字段。见手册:赋值。
{
  "type": "setver",
  "props": {
    "key": "<角色UUID>.好感度",
    "op": "+=",
    "aKind": "lit",
    "aLit": "5",
    "bKind": "none",
    "binOp": "+"
  }
}
核心字段:key(必填)、op(= += -= *= /=)、aKind / aLit / aVar、bKind / bLit / bVar、binOp。

调用片段

type: "callFragment" 跳去执行另一个片段,执行完回到此处继续(嵌套上限 30 层)。见手册:调用片段。
字段类型必填默认说明
fragmentIdstring✅""目标片段 id(同章节)

加载策略

type: "loadingStrategy" 提前准备后续剧情资源,支持图片、序列帧、差分立绘、Spine 和 Live2D。策略持续到下一条加载策略或当前脚本运行周期结束。
字段类型默认说明
modestring"auto"auto 自动预测;manual 加载资源清单
lookaheadnumber20自动模式检查后续 OP 数量,1–500。按运行时 OP 计数,不是编辑器 Block 数量;只扫描当前队列,不提前执行分支或跳转
executionstring"background"background 继续剧情并后台加载;wait 暂停脚本推进,等待加载完成
delayMsnumber2000等待模式显示加载界面前的延迟,0–60000 毫秒;0 表示立即显示
resourcesJsonstring"[]"手动资源清单的 JSON 数组字符串,格式如下
手动清单选择角色表情时使用 { "kind": "character", "characterId": "真实角色id", "expression": "真实表情名" },可加 skin 指定皮肤;选择场景使用 { "kind": "scene", "sceneId": "真实场景id" }。引用必须来自当前工程。角色表情会自动解析对应的静态或动态立绘资源及依赖,不需要手填模型文件路径。
{ "type": "loadingStrategy", "props": { "mode": "auto", "lookahead": 20, "execution": "wait", "delayMs": 2000, "resourcesJson": "[]" } }
等待从执行本 Block 时开始;2 秒是显示界面的阈值,不是放弃加载的超时。资源在阈值内准备好就直接继续,超出后显示默认游戏壳的 loading-screen,完成后关闭并继续。可以通过 internal.system.loading 系统槽位替换该界面。 默认界面使用“正在加载资源…”和“加载进度”智能组件;组件自动绑定只读系统变量 加载百分比(0–100)。普通文字也可写 {{加载百分比}}%。 进度按当前窗口去重后的已完成资源数统计,Spine / Live2D 在模型与依赖准备完成后计为完成,不代表下载字节比例或剩余时间;单个资源可能从 0% 直接到 100%。预测窗口变化时重新计算,停止后归零,不写入存档。 编辑画布可调整“预览百分比”检查外观,此示例值不会影响游戏运行。 后台失败会记录警告;等待模式失败会进入脚本错误处理。读档恢复不会重新等待已经跳过的手动预加载 Block。

等待

type: "wait" 见手册:等待。
字段类型必填默认说明
durationnumber1000等待时长(毫秒)。注意是真数字,不是字符串
waitForInputbooleanfalsetrue = 改为等玩家点击,忽略 duration

玩家输入

type: "playerInput" 弹出输入界面,等待玩家确认后把结果写入变量,再继续剧情。输入形态应与目标变量的声明类型一致。见手册:玩家输入。
字段类型必填默认说明
variablestring✅""结果写入的变量 key
valueTypestring✅"string"string / number / bool
titlestring✅"请输入"输入框标题
descriptionstring""说明文字
labelstring"玩家姓名"文本输入框左侧标签
showLabelbooleantrue是否显示文本输入框左侧标签
placeholderstring"请输入…"占位提示
confirmTextstring"确认"确认按钮文字
requiredbooleantrue是否必填
requiredTextstring"请填写后再继续"必填提示
minLength / maxLengthnumber0 / 20字符串长度限制,0 = 不限
minValue / maxValuenumber不限数字范围(valueType 为 number)
stepnumber1数字步进
trueText / falseTextstring"是" / "否"布尔选项文字(valueType 为 bool)

终止章节

type: "endChapter" 无参数。立即结束当前章节,进入 chapterOrder 的下一章。见手册:终止章节。

返回入口章节

type: "returnToEntry" 无参数。跳回工程的入口章节(常用于「回到标题」类流程)。见手册:返回入口章节。

进入 / 退出自动播放

type: "enterAutoPlay" / "exitAutoPlay" 成对使用,让剧情像放映一样自动推进。见手册:自动播放。
字段类型必填默认说明
allowInterrupt"true"/"false""true"仅 enterAutoPlay:"false" = 玩家不能打断(强制必看段)
exitAutoPlay 无参数。

界面与扩展

标准消息框

type: "systemMessage" 弹出提示或确认对话框。见手册:标准消息框。
{
  "type": "systemMessage",
  "props": {
    "mode": "confirm",
    "title": "确认",
    "message": "要保存进度吗?",
    "resultVariable": "save_confirmed"
  }
}
字段类型必填默认说明
modestring✅"alert"alert(仅确认)/ confirm(确认 + 取消)
titlestring✅"提示"标题
messagestring✅""正文
confirmTextstring"知道了"确认按钮文字
cancelTextstring"取消"取消按钮文字(仅 confirm)
tonestring"info"info / success / warning / danger
resultVariablestring""仅 confirm:把结果(布尔)写入的变量 key

显示界面

type: "showExtensionUI" 打开扩展或可视化 UI 编辑器制作的界面。见手册:显示界面。
字段类型必填默认说明
targetstring✅""三种写法:扩展id/界面id、ui:界面名(可视化 UI 编辑器的界面)、slot:槽位id
modalbooleanfalsetrue = 模态阻塞,关闭后剧情才继续
layerstring"topmost"层级:topmost / top / bottom / behind-scene
seekBehaviorstring"skip-if-seeking"快进 / 读档时的行为:skip-if-seeking / always-open(modal 为 true 时忽略)
interactablestring""三态:""(默认)/ "true" / "false",是否接收点击
size / positionstring""覆盖尺寸 / 位置,空 = 界面自身设定

隐藏界面

type: "hideExtensionUI"
字段类型必填默认说明
targetstring✅""与显示时的写法一致

调用扩展方法

type: "callExtensionFunction" 调用扩展提供的方法(解锁成就、加好感度等)。见手册:调用扩展方法。
{
  "type": "callExtensionFunction",
  "props": {
    "target": "avg.official.affection/add",
    "paramsJson": "{\"amount\":{\"kind\":\"lit\",\"value\":5}}"
  }
}
字段类型必填默认说明
targetstring✅""扩展id/方法id
paramsJsonJSON 字符串"{}"参数表;每个值形如 {"kind":"lit","value":…}(字面量)或 {"kind":"var","ref":"变量key"}(变量)

打开外部链接

type: "openExternalUrl"
{ "type": "openExternalUrl", "props": { "url": "https://example.com" } }
字段类型必填默认说明
urlstring✅""完整 HTTP/HTTPS 地址;生成时换成实际目标网址
在外部浏览器打开网页;读档、跳转回放和快进不会打开。编辑器预览先显示提示,由作者点击打开;Debug 使用真实打开行为。

解锁 Steam 成就

type: "unlockSteamAchievement"
{ "type": "unlockSteamAchievement", "props": { "apiName": "ACH_FIRST_CHAPTER" } }
字段类型必填默认说明
apiNamestring✅""Steamworks 已发布的成就 API 名称,区分大小写;示例名称必须换成实际配置
只在启用 Steam 的桌面导出游戏中生效;编辑器预览和读档重放不会解锁。它与本地成就扩展相互独立。

Steam 操作

type: "steamAction"
{
  "type": "steamAction",
  "props": { "action": "stat.add", "name": "CHAPTERS_READ", "value": "1" }
}
字段类型必填默认说明
actionstring✅"presence.set"presence.set / presence.clear / stat.set / stat.add / stat.get / achievement.progress / dlc.get / overlay.open / screenshot
namestring按 action"steam_display"状态键、统计 / 成就 API 名、DLC App ID;浮层使用 friends / community / achievements / store
valuestring按 action""状态值、统计数值、当前进度、商店 App ID 或截图说明
maximumstring进度操作"100"成就进度上限;当前进度必须小于上限,显示进度不会解锁成就
resultVariablestring查询操作""stat.get / dlc.get 写入的已声明变量;不可用时分别写入 0 / false
仅导出的 Steam 桌面游戏生效,读档重放不提交。统计必须是 Steamworks 已发布的 INT 统计,DLC 查询同时检查拥有和安装状态。示例中的统计名需要替换成真实配置。

其他

注释

type: "comment" 正文放 content,只在编辑器里可见,不参与游戏编译,用于给剧本留备注。见手册:注释。
以上为当前内置剧本类型;animateSprite、hideStageMask 仅兼容旧数据。paragraph 是编辑器内部保留类型,cmdDraft 是纯文本模式临时输入态,两者都不要作为新剧本指令生成。扩展类型必须以工程已安装扩展的声明为准。

最小片段调用示例

保存为 chapters/片段调用示例.json,并在已有工程索引中登记同名章节。此例没有资源占位符:先执行“问候”片段,结束后回到 main 的下一条指令。目标写的是 frag-example-greeting,不能写片段名“问候”。
{
  "id": "ch-example-call",
  "name": "片段调用示例",
  "fragments": [
    {
      "id": "frag-example-call-main",
      "name": "main",
      "blocks": [
        {
          "type": "callFragment",
          "props": {
            "fragmentId": "frag-example-greeting"
          }
        },
        {
          "type": "narration",
          "props": {
            "keepDialogue": false
          },
          "content": [
            {
              "type": "text",
              "text": "已回到主片段,继续故事。",
              "styles": {}
            }
          ]
        },
        {
          "type": "endChapter",
          "props": {}
        }
      ]
    },
    {
      "id": "frag-example-greeting",
      "name": "问候",
      "blocks": [
        {
          "type": "narration",
          "props": {
            "keepDialogue": false
          },
          "content": [
            {
              "type": "text",
              "text": "这是被调用片段中的旁白。",
              "styles": {}
            }
          ]
        }
      ]
    }
  ]
}

完整示例章节

一个小而全的章节文件,覆盖场景、音乐、对白、选项与片段跳转(片段 id 用了缩写示意,实际生成时保持全工程唯一即可):
{
  "id": "ch-1755500000000-1",
  "name": "第一章",
  "fragments": [
    {
      "id": "f2",
      "name": "main",
      "blocks": [
        {
          "type": "scene",
          "props": {
            "sceneId": "<场景UUID>",
            "sceneName": "教室",
            "transitionMode": "crossfade",
            "transitionDuration": "500"
          }
        },
        {
          "type": "sound",
          "props": {
            "soundType": "BGM",
            "soundId": "<音频UUID>",
            "uri": "bgm/日常.mp3",
            "loop": "true",
            "volume": "80"
          }
        },
        {
          "type": "narration",
          "props": {},
          "content": [
            {
              "type": "text",
              "text": "放学后的教室,只剩下我们两个人。",
              "styles": {}
            }
          ]
        },
        {
          "type": "dialogue",
          "props": {
            "characterId": "<角色UUID>",
            "characterName": "小雪",
            "expression": "微笑",
            "position": "center"
          },
          "content": [
            { "type": "text", "text": "今天想去哪里?", "styles": {} }
          ]
        },
        {
          "type": "branch",
          "props": {
            "title": "去哪里",
            "choices":
      "[{\"mode\":\"jump\",\"text\":\"出发\",\"fragmentId\":\"f3\"}]"
          }
        },
        {
          "type": "narration",
          "props": {},
          "content": [
            {
              "type": "text",
              "text": "片段执行完后,故事回到这里继续。",
              "styles": {}
            }
          ]
        },
        { "type": "endChapter", "props": {} }
      ]
    },
    {
      "id": "f3",
      "name": "去图书馆",
      "blocks": [
        {
          "type": "dialogue",
          "props": {
            "characterId": "<角色UUID>",
            "characterName": "小雪",
            "expression": "开心"
          },
          "content": [
            { "type": "text", "text": "那就走吧!", "styles": {} }
          ]
        }
      ]
    }
  ]
}
示例里的 <…UUID> 占位符必须替换成你工程里真实存在的 id,否则对应指令不会生效。角色 id 在 characters.json,场景 id 在 scenes.json。

让 AI 生成剧本

把资料喂给 AI 时,建议这样组织:
  1. 复制本页全文:结构规则和指令字段明细都在这一页。
  2. 附上工程实体对照表:从 characters.json、scenes.json、project.variables.json 里整理出「名字 → id」清单,以及每个角色可用的表情名。AI 只能引用这份清单里的 id,不能编造。
  3. 说明你要的剧情:章节名、片段规划(哪些分支、汇流到哪)、想要的演出效果。
再叮嘱 AI 几条硬规则(也可以直接把下面这段一起复制过去):
  • 只使用本页可创作的内置 type;禁止生成 animateSprite、hideStageMask、paragraph、cmdDraft。镜头使用 camera / stageAnimation,移除遮罩使用 stageMask 的 action: "remove"。
  • 不要生成编辑器自动维护的字段:voiceHash、isFirst、isLast、prevExpression、prevNameVariantId。
  • fragments[0] 必须命名为 main;branch / if / callFragment 的非空片段引用必须在同一章节里真实存在,且不能指向 main 或形成循环。字段明确允许空引用时,空字符串表示继续当前片段。
  • 新建章节 id、片段 id 必须在工程内唯一;新建 Block 可省略 id。修改已有内容时保留原 id、元数据和未涉及的工程配置。
  • 对白一句一个 dialogue,正文放 content,不要塞进 props。
  • 对白自带立绘显示(showCharacter 默认 true),不要在 dialogue 前额外加 showCharacter(那是重复调用);只有角色不说话就要登场时才用「角色登场」。
  • 一段对话结束、后面不再有对白时(尤其接镜头动画、场景切换等演出),把最后一句 dialogue / narration 的 keepDialogue 设为 false,自动隐藏对话框。
生成的文件放进工程 chapters/ 目录(文件名 = 章节名),再把章节名加进 project.json 的 chapterOrder 数组,重新打开工程即可在 Studio 里看到并继续编辑。也可以只让 AI 生成 fragments 里的 blocks 内容,粘贴合并进现有章节文件,这样可以完全不碰 id 和索引。

生成后检查清单

  1. 整个输出能被 JSON.parse 解析;一个章节文件只有一个顶层对象,没有 Markdown 围栏、注释、尾逗号或省略号。
  2. 章节有 id、name、非空 fragments;每个 Fragment 有 id、name、数组 blocks,第一项名为 main。
  3. Block 的 type 大小写正确,props 是对象;台词使用 content 文本数组。无参数指令也写 props: {}。
  4. 真布尔 / 数字与字符串布尔 / 数字按字段表分别处理;choices、conditions 等 JSON 字符串还要再解析一遍,确认内部结构正确。
  5. 所有非空片段引用在同章存在,目标不是 main,没有循环调用;所有资源、变量、扩展引用均来自提供的实体清单。
  6. 区分示例 id 与资源占位符:新章节 / 片段可以生成唯一 id;角色、场景、素材和扩展 id 不能编造。缺少信息时列出缺项,不输出假装能运行的占位引用。
  7. 文件名与章节名一致,登记 chapterOrder 并保持章节树排序一致;保留入口章节、原有 id 和其他工程配置。不要把索引片段覆盖为完整 project.json。

字段规范核对来源

本文按仓库中的以下定义核对。维护文档或编写生成器时,应同时核对结构、编辑器默认值和运行时读取逻辑,不能只根据旧示例推测:
  • src/studio/types/types.ts:磁盘 ChapterFile / FragmentData。
  • src/studio/types/project.ts、src/studio/shared/project-context.tsx:章节、片段结构及新建行为。
  • src/sdk/types/schema.ts:StoryBlock、片段元数据和调度事件配置边界。
  • src/studio/components/blocks/schema.ts、各指令组件的 propSchema:内置类型、可创作类型及默认参数。
  • src/studio/components/branch/branch-choice.ts、src/studio/components/blocks/if-condition.ts:选项、赋值与条件结构。
  • src/studio/components/preview/blocks-to-ops.ts:实际编译语义及缺省参数处理。

2.5.0:调整音量

type: "adjustVolume"。见调整音量。
字段类型默认说明
scopestring"track"track 指定音轨;type 整类声音
soundTypestring"BGM"BGM / SE / VOCAL
soundIdstring""指定音轨时与播放块 ID 一致;空值使用默认音轨
volumestring"100"0~100 百分比;0 静音但不停止
fadeDurationstring"0"渐变毫秒数,0~600000;剧情不等待渐变
{"type":"adjustVolume","props":{"scope":"type","soundType":"BGM","volume":"30","fadeDuration":"1000"}}
分类音量是当前及后续音轨的比例;指定音轨只调整该音轨当前播放。它们还会叠加项目与玩家音量。