Files
Echo/Assets/_Project/Docs/TaskSystem_Technical_Reference.md
T

187 lines
6.7 KiB
Markdown
Raw Normal View History

2026-07-08 19:53:15 +08:00
# 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);`