返回首页

游戏任务系统设计指南

核心设计思想:“You call me, I don’t call you”

基于回调机制的任务系统设计


引言:任务设计的常见误区

在游戏开发中,任务系统往往是最复杂、最容易出问题的模块之一。许多项目在设计任务系统时,会陷入一些”雾点”——那些看似合理、实则导致系统僵化难维护的设计陷阱。

常见的问题包括:

  • 任务条件千奇百怪 → 代码难以复用
  • 任务完成判定逻辑混乱 → 边界情况处理困难
  • 系统间交叉调用 → 维护困难,牵一发而动全身

本文将系统性地梳理这些问题,并提供一套清晰、可扩展的任务机制设计方案。


第一章:核心设计理念

1.1 “You call me” 设计思想

程序架构中有一种经典的设计思想:“I call you, you don’t call me”。这种单向交互思路的核心是:

当系统A需要系统B的数据时,由A主动访问B,而B从不主动向A提供帮助。

然而,在任务系统设计中,我们需要将这个思想逆转过来——

“You call me, I don’t call you”

这意味着:各业务系统(杀怪、道具、合成等)在特定事件发生时,主动回调通知任务系统,而不是让任务系统主动去轮询或监视各个系统。

这种设计模式的优势

优势说明
逻辑清晰避免系统间的交叉调用
性能提升减少不必要的轮询
易于扩展新增任务类型时无需修改核心代码
便于维护各系统职责明确,耦合度低

1.2 传统机制 vs 推荐机制

下图展示了两种机制的核心区别:

flowchart TB
    subgraph 传统机制["❌ 传统机制: I call you"]
        A1[任务系统] -->|主动查询| B1[杀怪系统]
        A1 -->|主动查询| C1[道具系统]
        A1 -->|主动查询| D1[合成系统]
        B1 -->|返回数据| A1
        C1 -->|返回数据| A1
        D1 -->|返回数据| A1
    end

    subgraph 推荐机制["✅ 推荐机制: You call me"]
        A2[任务系统]
        B2[杀怪系统] -->|怪物死亡回调| A2
        C2[道具系统] -->|道具获得回调| A2
        D2[合成系统] -->|合成成功回调| A2
    end

    style 传统机制 fill:#ffebee,stroke:#c62828
    style 推荐机制 fill:#e8f5e9,stroke:#2e7d32
    style A1 fill:#ffcdd2
    style A2 fill:#c8e6c9

关键区别

  • 传统机制:任务系统需要主动查询各个业务系统,耦合度高、扩展性差
  • 推荐机制:业务系统通过回调接口通知任务系统,实现真正的解耦

1.3 Tag 抽象机制

Tag 机制是实现”You call me”的核心手段。通过为任务目标和游戏实体分配 Tag,我们可以在回调时快速匹配相关的任务条件。

Tag 机制的工作流程

flowchart LR
    A[玩家行为] --> B{触发事件}
    B -->|击杀怪物| C[怪物死亡回调]
    B -->|获得道具| D[道具获得回调]
    B -->|合成物品| E[合成成功回调]

    C --> F[检查怪物Tag]
    D --> G[检查道具Tag]
    E --> H[检查合成物Tag]

    F --> I{匹配任务Tag?}
    G --> I
    H --> I

    I -->|是| J[增加任务进度]
    I -->|否| K[结束]
    J --> L[检查任务完成?]
    L -->|是| M[任务完成]
    L -->|否| K

    style A fill:#e3f2fd
    style I fill:#fff3e0
    style J fill:#e8f5e9
    style M fill:#c8e6c9

实际应用示例

假设有3个任务都涉及”巧克力蛋糕”:

任务条件Tag
帮助林克哥哥收集2个巧克力蛋糕CollectChocolateCake
料理妈妈的好帮手交给料理妈妈3个巧克力蛋糕CollectChocolateCake
买通兽人守卫准备3份巧克力蛋糕CollectChocolateCake

当玩家获得”巧克力蛋糕”时,道具系统触发回调:

IncreaseQuestProgress("CollectChocolateCake", item.stackCount)

任务系统只需检查所有任务条件中是否有匹配的 Tag,无需关心具体是什么道具


第二章:任务结束判定

2.1 结束条件的复杂性

设计任务时,最容易被忽视的是”任务如何结束”。

经典案例:采集车前草

任务要求:采集10颗车前草 地图资源:只有12颗可供采集

问题:如果玩家丢弃了3颗以上,任务实际上已经失败,但系统可能无法正确判定。

常见的错误解决方案

方案问题
道具不可丢弃玩家可能”吃掉”道具,问题依然存在
道具定时刷新玩家可能在原地等待刷新,而非挑战Boss
创建两种同名道具代码混乱,玩家体验差

2.2 Buff 层数判定法

正确的解决方案:利用 Buff 系统

核心思路

  1. 为玩家添加一个记录采集次数的 Buff(玩家不可见)
  2. 每次采集时增加 Buff 层数
  3. 在 Buff 触发时检查判定条件
flowchart TD
    A[任务开始] --> B[获得Buff层数]
    B --> C[采集车前草]
    C --> D[Buff层数+1]
    D --> E{检查判定}

    E -->|层数 - 持有数 > 3| F[任务失败]
    E -->|层数 >= 10| G[任务成功]
    E -->|其他情况| H[继续任务]

    H --> I[玩家行为]
    I -->|丢弃道具| J[重新判定]
    I -->|继续采集| C
    J --> E

    style A fill:#e3f2fd
    style E fill:#fff3e0
    style F fill:#ffcdd2
    style G fill:#c8e6c9

判定逻辑

if (Buff层数 - 当前持有数 > 3) → 任务失败
if (Buff层数 >= 10) → 任务成功

这种方法优雅地解决了边界情况,无需特殊处理。


第三章:策划与程序的协作

3.1 思维差异分析

“You call me”机制对于程序员来说非常清晰——只需在功能实现时预留回调点,提供统一的任务进度接口。但对于策划来说,需要更强的抽象能力。

维度程序员思维策划思维
对”Magic”的态度尽量避免(难以维护)合理使用(抽象工具)
实现关注点回调点 + 标准接口Tag 分配 + 事件规划
核心能力代码清晰可维护抽象与归纳能力

3.2 接口设计规范

任务系统应提供以下核心接口供业务系统调用:

接口名称参数说明
IncreaseQuestProgresstag, count增加指定 Tag 的任务进度
DecreaseQuestProgresstag, count减少指定 Tag 的任务进度
SetQuestCompletequestId直接完成指定任务
SetQuestFailquestId设置指定任务失败

系统整体架构

flowchart TB
    subgraph 核心层
        TaskSystem[任务系统]
        BuffSystem[Buff系统]
    end

    subgraph 业务系统层
        MonsterSys[杀怪系统]
        ItemSys[道具系统]
        CraftSys[合成系统]
        TalkSys[对话系统]
    end

    subgraph 回调接口
        IncProgress[IncreaseQuestProgress]
        DecProgress[DecreaseQuestProgress]
        SetComplete[SetQuestComplete]
        SetFail[SetQuestFail]
    end

    MonsterSys -->|怪物死亡| IncProgress
    ItemSys -->|获得道具| IncProgress
    CraftSys -->|合成成功| IncProgress
    TalkSys -->|对话完成| IncProgress
    BuffSystem -->|Buff触发| SetFail

    IncProgress --> TaskSystem
    DecProgress --> TaskSystem
    SetComplete --> TaskSystem
    SetFail --> TaskSystem

    style TaskSystem fill:#e3f2fd,stroke:#1976d2
    style BuffSystem fill:#e3f2fd,stroke:#1976d2

第四章:实战案例

案例:调制阿拉伯神油

任务背景

老汤姆需要一种特殊的药水来恢复活力。玩家需要收集4种材料,通过尝试不同的组合来调制出正确的药水。

设计要点

  1. 材料收集

    • 每种材料获得时触发 CollectMaterial Tag 回调
  2. 尝试记录

    • 每次合成尝试通过 Buff 层数记录
  3. 成功判定

    • 合成成功时触发 CraftSuccess 回调
  4. 对话变化

    • 根据尝试次数(Buff层数)改变NPC对话内容

实现细节

// 材料收集回调
OnItemGet("辣椒") → IncreaseQuestProgress("CollectMaterial", 1)
OnItemGet("汽油") → IncreaseQuestProgress("CollectMaterial", 1)

// 合成尝试回调
OnCraftAttempt() → AddBuffLayer("AttemptCount", 1)

// 合成成功回调
OnCraftSuccess("阿拉伯神油") → SetQuestComplete(questId)

// 对话时检查Buff层数
if (GetBuffLayer("AttemptCount") > 3) {
    ShowDialog("你终于成功了!")
} else {
    ShowDialog("再试试看别的组合?")
}

总结

本文系统性地介绍了游戏任务机制设计的核心思想。通过 “You call me, I don’t call you” 的设计模式,配合 Tag 抽象机制Buff 判定法,可以构建出清晰、可扩展、易维护的任务系统。

核心要点回顾

要点说明
回调机制业务系统主动通知任务系统,避免交叉调用
Tag 抽象用 Tag 统一任务目标的匹配逻辑
Buff 判定利用 Buff 层数解决复杂的结束条件判定
接口规范提供统一的进度增减和完成/失败接口

“君子生非异也,善假于物也”

系统和机制只是工具,用好工具才是优秀策划的真正体现。