187 lines
6.7 KiB
Markdown
187 lines
6.7 KiB
Markdown
# 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`:三种状态的 Icon(Sprite)
|
||
|
||
## 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);`
|