Files
aibis-dream/Assets/Scripts/SceneManagement/TimelineKit/README_TimelineKit.md
T

272 lines
8.2 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.
# TimelineKit 使用文档
TimelineKit 是 AIBIS Dream 项目中用于统一管理 Unity Timeline 播放的中心化系统。它基于 `PlayableDirector`,提供播放控制、Addressables 动态加载、Yarn 对话集成等功能。
---
## 目录
1. [系统架构](#系统架构)
2. [快速开始](#快速开始)
3. [配置 DirectorHandler](#配置-directorhandler)
4. [TimelineCenter API](#timelinecenter-api)
5. [Timeline 名称格式](#timeline-名称格式)
6. [Yarn 对话集成](#yarn-对话集成)
7. [代码调用示例](#代码调用示例)
8. [资源组织](#资源组织)
9. [Addressables 配置](#addressables-配置)
10. [常见问题](#常见问题)
---
## 系统架构
```
┌─────────────────┐ ┌──────────────────┐ ┌─────────────────┐
│ TimelineCenter │────▶│ DirectorHandler │────▶│ PlayableDirector│
│ (单例中心) │ │ (场景中的组件) │ │ (Unity 原生) │
└─────────────────┘ └──────────────────┘ └─────────────────┘
├── 注册/注销 Director
├── 播放控制 (播放/暂停/停止/重置)
├── 状态查询 (时间/时长)
└── 批量操作
```
- **TimelineCenter**:单例管理器,负责注册所有 Director 并统一调度
- **DirectorHandler**:挂载在带 `PlayableDirector` 的 GameObject 上,自动向 TimelineCenter 注册
- **TimelineYarnCommand**:提供 Yarn Spinner 命令,可在对话脚本中直接播放 Timeline
---
## 快速开始
### 1. 场景设置
1. 在场景中创建或选中一个 GameObject
2. 添加 **PlayableDirector** 组件,并分配默认的 Playable Asset
3. **将 PlayableDirector 的 Play On Awake 设为 false**,否则 Timeline 会在场景加载时立刻播放
4. 添加 **DirectorHandler** 组件
5. 在 DirectorHandler 中填写 **Timeline Name**(唯一标识,用于 PlayTimeline 时指定)
### 2. 播放 Timeline
```csharp
// 播放该 Director 自带的 Playable Asset
TimelineCenter.Instance.PlayTimeline("维修面板");
// 从 Addressables 加载并播放
TimelineCenter.Instance.PlayTimeline("卡扣/卡扣解锁");
```
---
## 配置 DirectorHandler
| 字段 | 说明 |
|------|------|
| **timelineName** | Director 的全局唯一名称,供 PlayTimeline 等 API 使用 |
| **director** | 关联的 PlayableDirector(通常与组件同一 GameObject,可自动查找) |
DirectorHandler 会在 `Start` 时自动向 TimelineCenter 注册,在 `OnDestroy` 时注销。
---
## TimelineCenter API
### 播放控制
| 方法 | 说明 |
|------|------|
| `PlayTimeline(string timelineName)` | 播放 Timeline(同步,不等待结束) |
| `PlayTimelineAsync(string name)` | 协程版本,播放完成后 yield 返回 |
| `StopTimeline(string timelineName)` | 停止播放 |
| `PauseTimeline(string timelineName)` | 暂停 |
| `ResumeTimeline(string timelineName)` | 恢复播放 |
| `ResetTimeline(string timelineName)` | 重置到开头 |
| `HideTimeline(string timelineName)` | 隐藏该 Director 的 GameObjectSetActive(false) |
### 状态查询
| 方法 | 说明 |
|------|------|
| `GetPlaybackTime(string name)` | 获取当前播放时间(秒) |
| `GetDuration(string name)` | 获取 Timeline 总时长(秒) |
### 扩展操作
| 方法 | 说明 |
|------|------|
| `SetPlaybackSpeed(string name, float speed)` | 设置播放速度 |
| `SeekToTime(string name, double time)` | 跳转到指定时间点 |
### 批量操作
| 方法 | 说明 |
|------|------|
| `PauseAll()` | 暂停所有已注册的 Timeline |
| `StopAll()` | 停止所有 |
| `ResetAll()` | 重置所有 |
---
## Timeline 名称格式
`timelineName` 支持两种格式:
| 格式 | 示例 | 说明 |
|------|------|------|
| **仅 Director 名** | `"维修面板"` | 播放该 Director 自带的 `playableAsset` |
| **Director 名/AddressableKey** | `"卡扣/卡扣解锁"` | 从 Addressables 加载 `Timeline/{AddressableKey}` 并播放 |
解析规则:若包含 `/`,则前半部分为 directorName,后半部分为 addressableKey;否则整个字符串为 directorName。
---
## Yarn 对话集成
TimelineYarnCommand 提供以下 Yarn 命令,可在 `.yarn` 文件中直接使用:
### play_timeline
播放 Timeline,**会等待播放完成**后再继续对话。
```yarn
// 播放自带 Timeline
<<play_timeline 维修面板>>
// 播放 Addressable Timeline
<<play_timeline 卡扣/卡扣解锁>>
```
### reset_timeline
重置 Timeline 到开头。
```yarn
<<reset_timeline 维修面板>>
```
### hide_timeline
隐藏 Timeline 所在的 GameObject。
```yarn
<<hide_timeline 维修面板>>
```
### start_timeline / wait_timeline
`start_timeline` 起播但**不等待**`wait_timeline` 等待**已经在播**的 Timeline 结束(不重头播)。叙事切场景时常用:黑屏下 `start` → 短 wait 稳住首帧 → `fade_out``wait_timeline`。完整约定见项目 Skill [`.cursor/skills/narrative-timeline-flow/SKILL.md`](../../../../.cursor/skills/narrative-timeline-flow/SKILL.md)。
```yarn
<<start_timeline 英里初登场>>
<<wait 0.2>>
<<fade_out>>
<<wait_timeline 英里初登场>>
<<hide_timeline 英里初登场>>
```
---
## 代码调用示例
### 直接播放(不等待)
```csharp
TimelineCenter.Instance.PlayTimeline("维修面板");
```
### 协程中等待播放完成
```csharp
IEnumerator PlayAndDoSomething()
{
yield return TimelineCenter.Instance.PlayTimelineAsync("卡扣/卡扣解锁");
// 播放完成后执行
Debug.Log("Timeline 播放完毕");
}
```
### 配合 ActionKit 使用
```csharp
ActionKit.Sequence()
.Coroutine(() => TimelineCenter.Instance.PlayTimelineAsync("卡扣/卡扣解锁"))
.Callback(() => BlockPuzzleYarnCommand.UnlockSystem())
.Start(this);
```
### 带完成回调的 DirectorHandler 播放
若直接持有 DirectorHandler 引用,可传入 `onComplete`
```csharp
// 仅适用于 Director 自带的 Asset,非 Addressable
directorHandler.Play(() => Debug.Log("播放完成"));
```
---
## 资源组织
- **Timeline 文件建议放在 `Assets/Animation` 文件夹下**,便于统一管理。
## Addressables 配置
对于需要动态加载的 Timeline 文件,**Addressable 的 Address 格式为 `Timeline/xxx`**。使用 `DirectorName/AddressableKey` 格式调用时,DirectorHandler 会加载:
```
Timeline/{AddressableKey}
```
因此需在 Addressables 中:
1. 创建或使用已有 Group(如「石头维修相关资源」)
2. 将 Timeline 资源加入 Group
3. **设置 Address 为 `Timeline/xxx` 格式**(如 `Timeline/卡扣解锁`
示例(`石头维修相关资源.asset` 中已有):
- `Timeline/卡扣解锁`
- `Timeline/卡扣锁定`
代码中调用时,`DirectorName/AddressableKey` 的 addressableKey 部分填 `卡扣解锁` 即可,DirectorHandler 会自动补全 `Timeline/` 前缀。
---
## 常见问题
### Q: Timeline 一进场景就自动播放?
将 PlayableDirector 组件的 **Play On Awake** 设为 **false**。否则 Unity 会在 Awake 时自动播放,与 TimelineCenter 的播放控制冲突。
### Q: Timeline 找不到?
确保场景中对应 GameObject 上有 DirectorHandler,且 `timelineName` 与调用时一致。DirectorHandler 在 `Start` 时注册,若场景未完全加载可能尚未注册。
### Q: Addressable 加载失败?
检查:
1. Addressable 的 Address 是否包含 `Timeline/` 前缀,或与 DirectorHandler 拼出的 key 一致
2. 资源已正确加入 Addressables Group
3. 控制台是否有 `Failed to load PlayableAsset` 等错误
### Q: 播放完成回调不触发?
- `PlayTimeline` / `PlayTimelineAsync` 不直接支持回调,需用协程或 ActionKit 在播放完成后再执行逻辑
- 直接调用 `directorHandler.Play(onComplete)` 时可使用回调,但仅适用于自带 Asset
### Q: 多个 Director 重名?
`timelineName` 必须全局唯一,否则后注册的会覆盖先前的。
---
## 相关文件
- `TimelineCenter.cs` - 中心管理器
- `DirectorHandler.cs` - Director 组件
- `TimelineYarnCommand.cs` - Yarn 命令注册