Files
tianshu-engine/docs/guide/SCENE_JSON_SPEC.md

256 lines
6.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Scene JSON 完整字段参考
## 顶层结构
```json
{
"assetBase": "",
"locales": { "path": "locales/", "languages": ["zh", "en"] },
"startScene": "intro",
"variables": { "trust": 50, "courage": 0 },
"introVideo": "__intro__/logo.mp4",
"menuVideo": "__intro__/menu_bg.mp4",
"scenes": { ... },
"chapters": [ ... ],
"achievements": [ ... ],
"endings": [ ... ]
}
```
| 字段 | 类型 | 必需 | 说明 |
|------|------|------|------|
| `assetBase` | string | 否 | 所有资源路径前缀,默认 `""`。设 `"demo/"``videoUrl: "intro/video.mp4"` 自动拼成 `demo/intro/video.mp4`。改 CDN 只需改这一行 |
| `locales` | object | 否 | 多语言配置。`path` 为 locale 文件目录(相对于 `assetBase``languages` 为支持的语言列表 |
| `startScene` | string | 是 | 开始场景的 ID |
| `variables` | object | 否 | 全局变量初始值 |
| `introVideo` | string | 否 | 开场视频路径 |
| `menuVideo` | string | 否 | 主菜单背景视频路径(自动循环播放) |
| `scenes` | object | 是 | 所有场景的集合key 为场景 ID |
| `chapters` | array | 否 | 章节列表 |
| `achievements` | array | 否 | 成就列表 |
| `endings` | array | 否 | 结局列表 |
---
## SceneNode
```typescript
interface SceneNode {
id: string
type?: 'video' | 'image'
videoUrl: string
imageUrl?: string
contentSize?: { w: number; h: number }
subtitleUrl?: string
subtitles?: Record<string, string>
choices?: Choice[]
hotspots?: Hotspot[]
qte?: QTEDefinition
nextScene?: string
onEnter?: Effect[]
loopStart?: number
loopEnd?: number
bgmUrl?: string
bgmVolume?: number
bgmCrossFade?: number
bgmDuckLevel?: number
bgmDuckFade?: number
videoMuted?: boolean
skippable?: boolean
}
```
| 字段 | 类型 | 说明 |
|------|------|------|
| `id` | string | 场景唯一标识 |
| `type` | string | `"video"` (默认) 或 `"image"`。image 类型展示图片+热点,不播放视频 |
| `videoUrl` | string | 视频文件路径。image 场景可为空 |
| `imageUrl` | string | 图片场景的图片路径 |
| `contentSize` | object | 内容基准分辨率 `{ w: 1280, h: 720 }`Hotspot 坐标基于此计算。用于 object-fit: contain 的偏移补偿 |
| `subtitleUrl` | string | 回退字幕路径。优先使用 `subtitles` |
| `subtitles` | object | 多语言字幕 `{ "zh": "...", "en": "..." }`。语言切换时自动选择 |
| `choices` | Choice[] | 选项列表 |
| `hotspots` | Hotspot[] | 可点击热点区域 |
| `qte` | QTEDefinition | QTE 定义 |
| `nextScene` | string | 无选项时的默认跳转场景 |
| `onEnter` | Effect[] | 进入场景时触发的效果 |
| `loopStart` | number | 循环起始时间(秒) |
| `loopEnd` | number | 循环结束时间(秒)。视频播放到 loopEnd 时跳回 loopStart |
| `bgmUrl` | string | 背景音乐路径 |
| `bgmVolume` | number | 背景音乐音量0-1默认 0.8 |
| `bgmCrossFade` | number | 背景音乐交叉淡化时长(秒),默认 2.0 |
| `bgmDuckLevel` | number | BGM Duck 压低比例0-1默认 0.35 |
| `bgmDuckFade` | number | BGM Duck 过渡时长(秒),默认 0.5 |
| `videoMuted` | boolean | 视频静音(配合独立 BGM 使用) |
| `skippable` | boolean | `false` = 禁止跳过(用于 QTE 等关键场景) |
---
## Choice
```typescript
interface Choice {
text: string
textKey?: string
prompt?: string
promptKey?: string
targetScene: string
conditions?: Condition[]
effects?: Effect[]
timeLimit?: number
}
```
| 字段 | 说明 |
|------|------|
| `text` | 选项文本(回退值) |
| `textKey` | i18n key优先于 `text`。如 `"intro.choice.left_door"` |
| `prompt` | 选择后浮现的提示文字(回退值) |
| `promptKey` | prompt 的 i18n key。如 `"left_door.prompt.handshake"` |
| `targetScene` | 目标场景 ID |
| `conditions` | 显示条件,不满足的选项隐藏 |
| `effects` | 选择后触发的效果 |
| `timeLimit` | 限时秒数0=不限时 |
---
## Hotspot
```typescript
interface Hotspot {
id: string
label: string
labelKey?: string
targetScene: string
x: number
y: number
width: number
height: number
showAt?: number
hideAt?: number
conditions?: Condition[]
effects?: Effect[]
}
```
| 字段 | 说明 |
|------|------|
| `id` | 热点唯一标识 |
| `label` | 显示标签(回退值) |
| `labelKey` | i18n key |
| `x, y` | 左上角坐标(像素,基于 contentSize |
| `width, height` | 尺寸(像素) |
| `showAt` | 视频时间(秒),此时间后显示。不设则始终可见 |
| `hideAt` | 视频时间(秒),此时间后隐藏 |
| `targetScene` | 点击后跳转的场景 |
| `conditions` | 显示条件 |
| `effects` | 点击后触发的效果 |
---
## QTEDefinition
```typescript
interface QTEDefinition {
triggerTime: number
prompt: string
promptKey?: string
keys: string[]
timeLimit: number
successScene: string
failScene: string
effects?: {
success: Effect[]
fail: Effect[]
}
}
```
| 字段 | 说明 |
|------|------|
| `triggerTime` | 触发时间(秒),视频播放到此时间弹出 QTE |
| `prompt` | 提示文字(回退值) |
| `promptKey` | i18n key。如 `"right_door.qte.dodge"` |
| `keys` | 有效按键列表,如 `["ArrowLeft", "ArrowRight", "a", "d"]` |
| `timeLimit` | 限时秒数 |
| `successScene` | 成功跳转场景 |
| `failScene` | 失败/超时跳转场景 |
| `effects` | 成功/失败分别触发效果 |
---
## 其他类型
### Condition
```typescript
interface Condition {
variable: string
op: '>' | '<' | '>=' | '<=' | '==' | '!='
value: number | string | boolean
}
```
### Effect
```typescript
interface Effect {
type: 'set' | 'add'
target: string
value?: number | string | boolean
}
```
- `set` — 设置变量值
- `add` — 变量增加/减少
### ChapterInfo
```typescript
interface ChapterInfo {
id: string
label: string
labelKey?: string
startScene: string
thumbnail?: string
defaultVariables?: Record<string, number>
}
```
### AchievementDef
```typescript
interface AchievementDef {
id: string
title: string
titleKey?: string
description: string
descKey?: string
icon?: string
hidden?: boolean
condition: Condition
}
```
### EndingDef
```typescript
interface EndingDef {
id: string
label: string
labelKey?: string
sceneId: string
chapterId?: string
thumbnail?: string
}
```
### LocalesConfig
```typescript
interface LocalesConfig {
path: string
languages: string[]
}
```