Files
Echo/Assets/_Project/Docs/TaskSystem_Technical_Reference.md
2026-07-08 20:42:51 +08:00

187 lines
6.7 KiB
Markdown
Raw Permalink 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.
# TaskSystem 技术参考
本文档定义并说明项目内的“任务系统(TaskSystem)”以及它如何驱动任务面板 UI(TaskPanel)。
相关脚本:
- `Assets/_Project/Scripts/Core/TaskSystem/TaskService.cs`
- `Assets/_Project/Scripts/Core/TaskSystem/TaskData.cs`
- `Assets/_Project/Scripts/UI/Tasks/TaskPanelController.cs`
- `Assets/_Project/Scripts/UI/Tasks/TaskListItemView.cs`
相关 UI 搭建与布局参考:
- `Assets/_Project/Docs/TaskSystem_UI_Setup.md`
## 1. 设计目标
- 任务数据与 UI 解耦:代码不硬编码层级路径,通过 Inspector 槽位绑定 UI。
- 列表项可做成 Prefab:运行时动态实例化到 ScrollView Content。
- 任务状态可被外部系统调用修改:支持添加、移除、状态切换(待做/完成/超时)。
- 超时逻辑由任务系统统一处理:当任务设置了超时时间,自动切换为“超时”状态。
## 2. 数据模型
### 2.1 TaskData(任务静态数据)
文件:`TaskData.cs`
- 类型:`ScriptableObject`
- 字段:
- `id`:任务 ID(全局唯一)
- `shortName`:短任务名(列表显示)
- `description`:任务描述(详情显示)
用途:
- 设计人员可以在 Project 里创建多个 `TaskData` 资源,作为“任务定义库”。
### 2.2 TaskEntry(任务运行时状态)
文件:`TaskEntry.cs`
- 运行时由 `TaskService` 创建与维护
- 字段:
- `id` / `data`
- `status``Todo | Completed | Expired`
- `addedAt`:加入时间(秒)
- `expiresAt`:过期时间(秒,0 表示不超时)
- `scheduledRemoveAt`:计划移除时间(秒,0 表示不自动移除)
## 3. 任务状态与规则
状态枚举:`TaskStatus``TaskStatus.cs`
- `Todo`:待做
- `Completed`:完成
- `Expired`:超时
规则(当前版本由系统统一规定):
- 添加任务默认状态为 `Todo`
- 当任务设置了 `timeoutSeconds > 0`
- 到达 `expiresAt` 后,系统会自动将状态改为 `Expired`
- 任务移除策略:
- 默认不自动移除(`autoRemove...AfterSeconds < 0`
- 可在 `TaskService` Inspector 中设置:
- `autoRemoveCompletedAfterSeconds`
- `autoRemoveExpiredAfterSeconds`
- 当状态切为 `Completed/Expired` 时,会按配置自动排期移除
时间基准:
- `TaskService.useUnscaledTime = true` 时,使用 `Time.unscaledTime`
- `false` 时,使用 `Time.time`
## 4. TaskService(系统 API
文件:`TaskService.cs`
### 4.1 调用方式
- 推荐:在外部脚本中通过 Inspector 挂引用(Slot)调用
- 可选:使用单例 `TaskService.Instance`(前提是场景里存在一个 TaskService
### 4.2 公开 API(最常用)
- 添加(若已存在则失败):
- `bool AddTask(TaskData data, float timeoutSeconds = -1f)`
- 添加或更新(若已存在则更新 data,并可选重置状态):
- `TaskEntry AddOrUpdateTask(TaskData data, float timeoutSeconds = -1f, bool resetStatusToTodo = false)`
- 移除:
- `bool RemoveTask(string taskId)`
- 改状态:
- `bool SetTaskStatus(string taskId, TaskStatus status)`
- 查询:
- `bool TryGetTask(string taskId, out TaskEntry task)`
- `IReadOnlyList<TaskEntry> Tasks`
### 4.3 事件(用于驱动 UI
- `Changed`:任意任务列表/任务内容变化都会触发
- 细粒度事件(可按需订阅):
- `TaskAdded`
- `TaskUpdated`
- `TaskRemoved`
- `TaskStatusChanged`
## 5. UI 对接(TaskPanel
### 5.1 TaskPanelController(面板控制器)
文件:`TaskPanelController.cs`
它做的事情:
- 监听 `TaskService.Changed`,重建列表
- 实例化 `taskItemPrefab``listContent`
- 点击列表项时,更新右侧详情文本(`titleText/detailText`
Inspector 需要绑定的槽位:
- `taskService`:场景里的 TaskService
- `listContent`Scroll View 的 `Viewport/Content`
- `taskItemPrefab`:任务按钮 Prefab(带 `TaskListItemView`
- `detailText`:右侧详情 TMP
- `titleText`:可选(右侧标题 TMP
### 5.2 TaskListItemView(列表项视图)
文件:`TaskListItemView.cs`
它做的事情:
- 通过 Reach 的 `ButtonManager.SetText()` 设置按钮文本
- 按任务状态设置按钮的 Icon 与颜色(待做/完成/超时)
- 将按钮 `onClick` 绑定为“通知 TaskPanelController 选中该任务”
Inspector 需要绑定的槽位:
- `button`Reach 的 `ButtonManager`(可不填,会在 Awake 尝试自动从同物体 GetComponent
- `todoIcon/completedIcon/expiredIcon`:三种状态的 IconSprite
## 6. 编辑器搭建步骤(从 0 到能跑)
目标场景:
- `Assets/_Project/Scenes/Test/UI_Test.unity`
### 6.1 创建 TaskData 资产
1) Project 里新建文件夹(建议):`Assets/_Project/Data/Tasks`
2) 右键 -> Create -> TaskSystem -> Task Data
3) 填写:
- `id`(例如:`task_open_door`
- `shortName`(例如:`打开仓库门`
- `description`(例如:`去工具间找到钥匙,然后打开仓库门。`
### 6.2 制作任务列表项 Prefab(按钮)
1) 在 `UI_Test` 场景里,选中你当前用于测试的任务按钮(例如 `BtnTaskPrefab`
2) 确认该按钮上存在 Reach 的 `ButtonManager` 组件
3) Add Component`TaskListItemView`
4) (可选但推荐)Add Component`Layout Element`,设置 `Preferred Height`(例如 56/64),让列表项高度稳定
5) 将该按钮拖拽到 Project 生成 Prefab(建议放:`Assets/_Project/Prefabs/UI/Tasks/TaskListItem.prefab`
### 6.3 在场景中加入 TaskService
1) Hierarchy 新建空物体:`TaskSystem`
2) Add Component`Core.TaskSystem.TaskService`
3) 配置(可选):
- `Dont Destroy On Load`:是否跨场景保留
- `Auto Remove Completed/Expired After Seconds`:是否自动移除
### 6.4 绑定 TaskPanelController
1) 在 `UI_Test` 场景中选中 `TaskPanelRoot`(或你认为最合适的面板根)
2) Add Component`UI.Tasks.TaskPanelController`
3) 依次绑定槽位:
- `Task Service` -> `TaskSystem(TaskService)`
- `List Content` -> `Left_TaskList/Scroll View/Viewport/Content`
- `Task Item Prefab` -> 第 6.2 步创建的 Prefab
- `Detail Text` -> `Right_TaskDetails/DetailText`
- `Title Text` ->(可选)右侧标题 TMP
### 6.5 (可选)使用 TaskBootstrap 快速验证 UI
1) 在 `TaskSystem` 物体上 Add Component`Core.TaskSystem.TaskBootstrap`
2) `Tasks To Add` 列表中拖入若干 `TaskData`
3) (可选)设置 `Timeout Seconds`,观察任务在超时后自动变为“超时”
## 7. 外部系统如何调用(示例)
示例:当玩家触发某个交互后,完成任务:
- 在你的交互脚本里持有一个 `TaskService` 引用(Inspector 槽位)
- 调用:
- `taskService.SetTaskStatus(taskId, TaskStatus.Completed);`
示例:添加一个限时任务:
- `taskService.AddTask(taskData, timeoutSeconds: 60f);`