Appearance
场景配置 JSON 格式
用于导入导出场景完整配置,包含节点定义、动画组和场景规则。
顶层结构
json
{
"version": 1,
"name": "场景名称",
"definition": {
"version": 2,
"nodes": [],
"animationGroups": [],
"rules": []
}
}| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
version | number | 是 | 固定为 1 |
name | string | 是 | 场景名称 |
definition | object | 是 | 场景定义容器 |
definition
| 字段 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
version | number | 否 | 2 | 场景定义版本。当前建议写 2 |
nodes | array | 是 | - | 节点数组 |
animationGroups | array | 否 | [] | 动画组数组 |
rules | array | 否 | [] | 场景规则数组 |
definition.nodes(节点)
每个节点代表场景中的一个视觉/音频元素。
| 字段 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
id | string | 是 | - | 节点唯一标识 |
assetId | string | 条件 | - | 关联的场景资源 ID。camera / slot / audio 节点无需填写,其他类型必须填写 |
kind | string | 是 | - | 节点类型,取值见下表 |
visible | boolean | 否 | true | 是否可见 |
opacity | number | 否 | 1 | 不透明度(0~1) |
x | number | 否 | 0.5 | 横向位置(归一化 0~1) |
y | number | 否 | 0.5 | 纵向位置(归一化 0~1) |
scaleX | number | 否 | 1 | 横向缩放 |
scaleY | number | 否 | 1 | 纵向缩放 |
rotation | number | 否 | 0 | 旋转角度 |
anchorX | number | 否 | 0.5 | 锚点 X |
anchorY | number | 否 | 0.5 | 锚点 Y |
fit | string | 否 | "contain" | 图片适配方式 |
isLookAtPointer | boolean | 否 | false | 是否跟随指针(仅 Cubism) |
defaultState | object | 否 | {} | 默认状态(如 stateName / autoplay / loop / volume) |
children | array | 否 | [] | 子项列表(仅 slot 节点) |
kind 取值
| 值 | 说明 | 是否需要 assetId |
|---|---|---|
cubism | Live2D Cubism 模型 | 是 |
spine | Spine 骨骼动画 | 是 |
image | 静态图片 | 是 |
video | 视频 | 是 |
audio | 音频 | 否 |
slot | 角色位容器 | 否 |
camera | 摄像机(每个场景自动插入一个) | 否 |
节点约束
- 每个节点的
id必须唯一,不能为空。 camera节点 ID 固定为scene_camera,每个场景最多一个。slot节点可以包含children子项列表。audio节点的assetId若留空则不会渲染,但不会被拒绝。
children 子项(slot 节点下)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
id | string | 是 | 子项唯一标识 |
assetId | string | 是 | 关联的资源 ID(只能引用 cubism / spine / image / image_variant 类型资源) |
label | string | 否 | 子项显示标签 |
defaultState | object | 否 | 默认展示状态 |
definition.animationGroups(动画组)
每个动画组包含一组按序执行的动画定义。
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
id | string | 否 | 动画组稳定 ID。推荐显式填写;若省略,导入时会自动补生成 |
name | string | 是 | 动画组名称,场景内不可重复 |
animations | array | 否 | 动画定义列表 |
动画组约束
name不能为空,同一场景内不能有重名的动画组。id若填写,建议在同一场景内保持唯一且稳定。
animations 条目
| 字段 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
nodeId | string | 否 | - | 目标节点 ID(delay 类型无需填写) |
withPrevious | boolean | 否 | false | 是否与上一动画并行执行 |
duration | number | 否 | - | 动画持续时间(秒) |
delay | number | 否 | - | 延迟时间(秒)。若填写此项则为纯延时步骤,无需 nodeId / duration |
easing | string | 否 | "linear" | 缓动函数:linear / easeIn / easeOut / easeInOut |
set | object | 否 | - | 即时状态变更 |
to | object | 否 | - | 目标属性变换 |
by | object | 否 | - | 相对属性变换 |
play | object | 否 | - | 播放动作 |
set 即时状态
| 字段 | 类型 | 说明 |
|---|---|---|
visible | boolean | 设置可见性 |
zIndex | number | 设置层级 |
activeChildId | string | 设置 slot 节点的活跃子项 |
stateName | string | 设置节点状态名称 |
to / by 变换属性
| 字段 | 类型 | 说明 |
|---|---|---|
x | number | 横向位置 |
y | number | 纵向位置 |
scaleX | number | 横向缩放 |
scaleY | number | 纵向缩放 |
rotation | number | 旋转角度 |
opacity | number | 不透明度 |
anchorX | number | 锚点 X |
anchorY | number | 锚点 Y |
volume | number | 音量 |
play 播放动作
| 字段 | 类型 | 说明 |
|---|---|---|
actionName | string | 要播放的动作名称 |
transport | string | 播放控制 |
definition.rules(场景规则)
| 字段 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
id | string | 是 | - | 规则唯一标识 |
title | string | 是 | - | 规则标题 |
sourceType | string | 否 | "character" | 触发来源:user / character / system |
textCondition | object | 否 | - | 文本/正则匹配条件。未添加时可省略 |
ifExpr | string | 否 | "" | if 条件表达式 |
whenExpr | string | 否 | "" | when 条件表达式 |
animationGroupId | string | 否 | - | 触发后播放的动画组 ID |
isEnabled | boolean | 否 | true | 是否启用 |
textCondition
textCondition 用于描述文本/正则匹配条件。
| 字段 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
type | string | 是 | - | 匹配类型:regex / text |
pattern | string | 是 | - | 匹配内容。regex 时为正则表达式;text 时支持 `A |
replacePattern | string | 否 | "" | 仅 regex 模式使用的替换模板 |
keepMatchedText | boolean | 否 | true | 仅 text 模式使用。true 表示保留命中文本,false 表示删除命中文本 |
isCaseSensitive | boolean | 否 | false | 是否区分大小写 |
isGlobal | boolean | 否 | true | 是否全局匹配 |
规则约束
id不能为空,同一场景内不能有重复 ID。title不能为空。- 若存在
textCondition: pattern必须非空。type == "regex"时,pattern必须是合法正则表达式。replacePattern若非空,必须是合法替换模板。type == "text"时,pattern表示简单字面量匹配,支持A|B|C候选词语法。type == "text"时不支持MatchN或$1这类正则捕获变量。ifExpr/whenExpr若非空则必须是合法条件表达式。animationGroupId若不为空,建议引用当前场景中已存在的动画组 ID;若引用失效,导入后仍允许保留。- 若
textCondition缺失,则该规则不会按文本匹配改写文本,但仍可仅通过ifExpr / whenExpr触发动作。
旧结构兼容
当前导入仍兼容旧版平铺字段:
searchPatternreplacePatternmatchTypekeepMatchedTextisCaseSensitiveisGlobalanimationGroupName
兼容规则:
- 旧规则若确实存在
searchPattern或replacePattern,会在读取时迁移为textCondition - 旧规则若只有
ifExpr / whenExpr,不会补出空的textCondition - 旧
animationGroupName会在可唯一匹配时迁移为animationGroupId
最小示例
json
{
"version": 1,
"name": "我的场景",
"definition": {
"version": 2,
"nodes": [
{
"id": "main",
"assetId": "asset-uuid-here",
"kind": "cubism",
"isLookAtPointer": true
}
],
"animationGroups": [],
"rules": []
}
}完整示例
json
{
"version": 1,
"name": "教室场景",
"definition": {
"version": 2,
"nodes": [
{
"id": "bg",
"assetId": "bg-classroom-uuid",
"kind": "image",
"x": 0.5,
"y": 0.5,
"scaleX": 1.2,
"scaleY": 1.2
},
{
"id": "character",
"assetId": "chara-yuki-uuid",
"kind": "cubism",
"x": 0.3,
"y": 0.7,
"scaleX": 0.8,
"scaleY": 0.8,
"isLookAtPointer": true,
"defaultState": {
"stateName": "idle"
}
},
{
"id": "slot_left",
"assetId": "",
"kind": "slot",
"x": 0.2,
"y": 0.5,
"children": [
{
"id": "child_1",
"assetId": "npc-a-uuid",
"label": "同学A",
"defaultState": { "stateName": "sit" }
},
{
"id": "child_2",
"assetId": "npc-b-uuid",
"label": "同学B"
}
]
}
],
"animationGroups": [
{
"id": "group_wave",
"name": "wave",
"animations": [
{
"nodeId": "character",
"duration": 0.5,
"easing": "easeInOut",
"play": { "actionName": "wave_hand" }
}
]
},
{
"id": "group_enter",
"name": "enter",
"animations": [
{
"delay": 0.5
},
{
"nodeId": "character",
"duration": 1.0,
"easing": "easeOut",
"to": { "x": 0.3, "opacity": 1 },
"set": { "visible": true }
}
]
}
],
"rules": [
{
"id": "rule_wave",
"title": "挥手响应",
"sourceType": "user",
"textCondition": {
"type": "text",
"pattern": "你好|挥手|hi",
"keepMatchedText": true,
"isCaseSensitive": false,
"isGlobal": true
},
"animationGroupId": "group_wave",
"isEnabled": true
},
{
"id": "rule_greet",
"title": "欢迎入场",
"sourceType": "system",
"ifExpr": "SenderName == '系统'",
"animationGroupId": "group_enter",
"isEnabled": false
}
]
}
}AI 生成约束
- 场景名称
name不能为空。 - 节点的
id不能为空且不能重复。摄像机节点id固定为scene_camera。 - 非
camera/slot/audio节点的kind必须填写有效的assetId。 - 动画组
name不能为空且不能重复。 - 规则
id不能为空且不能重复,title不能为空。 - 规则若填写
animationGroupId,应优先引用animationGroups中已存在的id。 - 若提供
textCondition: pattern必须非空。type == "regex"时,pattern必须是合法正则表达式。type == "text"时,pattern应使用简单字面量或A|B|C候选词形式。ifExpr/whenExpr若非空必须是合法条件表达式。
常见错误
- 节点
id为空或重复 → 校验失败,提示对应节点错误 kind取值不合法 → 校验失败- 非
camera/slot/audio节点缺少assetId→ 校验失败 - 动画组
name为空或重复 → 校验失败 - 规则
id为空或重复 → 校验失败 textCondition.type == "regex"且pattern不是合法正则 → 校验失败,提示具体错误replacePattern不是合法替换模板 → 校验失败,提示具体错误ifExpr/whenExpr非法 → 校验失败,提示具体错误