# 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 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);`