Q48: 如何设计任务系统?
核心结论
任务系统不是“一个列表加几个计数器”,而是“任务定义、进度监听、状态流转和奖励发放”的组合系统。
真正需要先设计清楚的是:
- 任务状态机
- 任务条件如何监听和更新
- 任务链和前置条件怎么表达
- 奖励发放和任务完成如何防重复
如果这些边界不稳,任务越多,维护成本越高。
一、任务系统真正负责什么
它通常需要处理:
- 任务接取
- 任务条件推进
- 任务完成判定
- 奖励发放
- 任务链解锁
这意味着任务系统既是内容驱动系统,也是状态机系统。
二、先把任务定义和任务实例分开
1. 任务定义
描述静态规则,例如:
- 任务类型
- 前置条件
- 目标列表
- 奖励
- 可重复规则
2. 任务实例
描述玩家当前状态,例如:
- 是否已接
- 当前进度
- 是否已完成
- 是否已领奖
这两层不分开,后续会很难支持日常、周常、链式和动态任务。
三、任务系统最关键的是状态流转
一个常见状态机会包含:
- 未解锁
- 可接取
- 进行中
- 可提交
- 已完成
某些任务还会有:
- 已失败
- 已放弃
- 等待重置
关键是每次状态变化必须有明确触发条件,而不是散落在各子系统里临时修改。
四、任务进度更新为什么不能全靠轮询
如果每次都全量扫描玩家状态判断任务是否完成,代价会很高。
更常见也更稳妥的做法是事件驱动:
- 击杀事件触发任务计数
- 拾取事件触发收集任务推进
- 对话事件触发剧情任务推进
也就是说,任务系统更像一个事件订阅者,而不是一个不断自查的大轮询器。
五、任务条件要标准化表达
任务条件常见包括:
- 击杀指定目标
- 收集物品
- 到达区域
- 完成对话
- 使用某物品
- 达到某数值
如果每类条件都写成独立硬编码流程,任务量一大后会非常难维护。
更合理的做法通常是:
- 用标准条件类型加参数描述
- 由运行时统一解释和推进
六、任务链和前置依赖要明确
复杂任务系统往往不在单任务,而在任务之间的依赖关系。
例如:
- 主线解锁支线
- 完成 A 才能接 B
- 失败后回退或重置分支
这类依赖如果没有明确建模,后面很容易出现:
- 错误解锁
- 重复领取
- 任务卡死
七、奖励发放必须和任务状态提交一起看
任务完成和奖励到账不能只靠客户端按钮顺序保证。
更稳妥的做法是:
- 服务端确认任务可提交
- 提交和发奖走统一链路
- 奖励发放具备幂等
否则断线重试或重复点击很容易产生双发。
八、工程上更稳妥的设计
常见做法是:
- 任务配置表描述静态规则
- 玩家任务实例记录当前状态
- 事件系统驱动进度推进
- 任务提交统一做合法性校验和发奖
这样内容扩展和系统稳定性都更容易兼顾。
九、常见误区
1. 任务系统只是配置问题
不对。真正难的是状态流转和事件驱动推进。
2. 所有任务都能靠一堆脚本随便拼
短期灵活,长期会变成大量不可追踪的例外。
3. 客户端显示完成就等于任务完成
不对。最终完成和发奖必须由权威逻辑确认。
参考资料
- 各类在线游戏任务、成就与事件驱动进度系统实践资料
