ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

MaaAssistantArknights 任务流程协议(tasks.json)完整字段参考与源码级实现解析

2026/9/13 13:38:37 拓冰建站 浏览量
MaaAssistantArknights 任务流程协议(tasks.json)完整字段参考与源码级实现解析 MaaAssistantArknights 任务流程协议tasks.json完整字段参考与源码级实现解析【免费下载链接】MaaAssistantArknights《明日方舟》小助手全日常一键长草| A one-click tool for the daily tasks of Arknights, supporting all clients.项目地址: https://gitcode.com/GitHub_Trending/ma/MaaAssistantArknights本文基于 任务流程协议文档系统讲解 MaaAssistantArknights 中resource/tasks任务流程的完整字段语义、表达式计算、模板任务与虚任务机制并结合 MaaCore 中TaskData与ProcessTask的源码实现说明每个字段在运行时是如何被解析、继承与执行的帮助你既能正确编写tasks.json也能理解其底层调度原理。一、任务流程协议是什么从 tasks.json 到任务执行MaaAssistantArknights 的日常流程编排依赖一份 JSON 任务配置文件tasks.json。每个顶层 key 是一个任务名value 描述该任务如何识别屏幕与识别到之后做什么。从源码结构看整条链路分为两层配置层TaskData 负责加载、合并与展开任务定义。TaskData::load支持传入单个 JSON 文件或一个目录——目录模式下会用recursive_directory_iterator递归收集所有.json文件并逐 key 合并重复 key 会报错。因此模板图/任务文件可放在子文件夹下的约定在加载与识别两侧都成立。执行层ProcessTask 是任务流程的实际驱动器。ProcessTask::run()维护一个待识别任务列表to_be_recognized每轮调用find_and_run_task对列表做识别并执行命中的任务再根据结果决定下一轮列表// src/MaaCore/Task/ProcessTask.cpp (ProcessTask::run 的简化逻辑) case NodeStatus::RetryFailed: to_be_recognized cur_task_ptr-on_error_next; // 重试失败 - onErrorNext case NodeStatus::Runout: to_be_recognized next_task_ptr-exceeded_next; // 达到 maxTimes - exceededNext case NodeStatus::Success: to_be_recognized next_task_ptr-next; // 成功 - next也就是说字段next/exceededNext/onErrorNext并非抽象概念而是直接对应调度循环中三个分支的下一轮待识别列表若下一轮列表为空则整个流程结束return true。这正是文档中不填写next默认执行完当前任务直接停止的源码依据。二、完整字段一览JSON 文件不支持注释下文示例中的注释仅用于演示说明请勿直接复制使用。2.1 通用字段所有 algorithm 可用{ TaskName: { // 任务名带 时可能为特殊任务字段默认值会有不同 baseTask: xxx, // 以 xxx 任务为模板生成任务派生任务 algorithm: MatchTemplate, // 可选项识别算法类型不填写时默认为 MatchTemplate // - JustReturn: 不进行识别直接执行 action // - MatchTemplate: 匹配图片 // - OcrDetect: 文字识别 // - FeatureMatch: 特征匹配 action: ClickSelf, // 可选项识别到后的动作不填写时默认为 DoNothing // - ClickSelf: 点击识别到的位置目标范围内随机点 // - ClickRect: 点击指定区域specificRect不建议使用 // - DoNothing: 什么都不做 // - Stop: 停止当前任务 // - Swipe: 滑动specificRect 与 rectMove // - Input: 输入文本要求 algorithm 为 JustReturn sub: [SubTaskName1, SubTaskName2], // 可选项子任务不推荐使用。执行完当前任务后依次执行 // 可以套娃但要注意不要写出死循环 subErrorIgnored: true, // 可选项是否忽略子任务的错误默认 false // false 时子任务出错则本任务视为出错 next: [OtherTaskName1, OtherTaskName2], // 可选项执行完当前任务和 sub 后下一个要执行的任务 // 从前向后依次识别执行第一个匹配上的 // 不填写默认执行完直接停止 // 相同任务第一次识别后不再重复识别 // next: [ A, B, A, A ] - [ A, B ] // 不允许 JustReturn 型任务位于非最后一项 maxTimes: 10, // 可选项该任务最大执行次数不填写时默认无穷大 // 达到上限后若存在 exceededNext 则执行它否则任务停止 exceededNext: [OtherTaskName1], // 可选项达到最大执行次数后要执行的任务 // 不填写则达到上限即停止填写后执行这里而不是 next onErrorNext: [OtherTaskName1], // 可选项执行出错重试耗尽时后续要执行的任务 preDelay: 1000, // 可选项识别到后延迟多久才执行 action毫秒默认 0 postDelay: 1000, // 可选项action 完成后延迟多久才识别 next毫秒默认 0 roi: [0, 0, 1280, 720], // 可选项识别范围 [ x, y, width, height ] // 以 1280 * 720 为基准自动缩放不填默认全屏 // 尽量填写缩小范围可减少性能消耗、加快识别 cache: false, // 可选项是否使用缓存默认 false // 开启后永远只在第一次识别到的位置继续识别 // 仅适用于目标位置完全不会变的任务 rectMove: [0, 0, 0, 0], // 可选项识别后的目标移动不建议使用 // action 为 Swipe 时有效且必选表示滑动终点 // 以 1280 * 720 为基准自动缩放 reduceOtherTimes: [OtherTaskName1], // 可选项执行后减少其他任务的执行计数 // 例如执行了使用理智药说明上一次点蓝色开始行动没生效 specificRect: [100, 100, 50, 50], // action 为 ClickRect 时有效且必选指定点击位置范围内随机一点 // action 为 Swipe 时有效且必选滑动起点 // 以 1280 * 720 为基准自动缩放 specialParams: [int, ...], // 某些特殊识别器需要的参数 // action 为 Swipe 时可选[0] duration[1] 额外滑动方向 // 0 不启用1/2/3/4 分别为上/下/左/右 // [2]/[3] 为轨迹缓入/缓出斜率需乘 10 输入默认均为 10 // 正常进入并缓出时建议 [2]37, [3]1 highResolutionSwipeFix: false // 可选项是否启用高分辨率滑动修复默认 false } }从源码看这些字段的实际消费点ProcessTask::run_taskpreDelay在动作执行前sleep(task-pre_delay)postDelay在动作完成后、执行子任务前生效且可被运行时的set_post_delay按任务名覆盖对CBA这类名称会逐层向上查找覆盖值见calc_post_delay。reduceOtherTimes对应源码中的注释示例进入使用理智药的界面了相当于上一次点蓝色开始行动没生效所以要给蓝色开始行动的次数减一与文档说明完全一致。maxTimes的判定分Pre/Post两种时机Pre 在任务计数检查时直接返回RunoutPost 在子任务全部跑完后判定。运行时的set_times_limit同样支持对CBA名称逐层继承次数上限calc_time_limit。JustReturn型任务在 find_first 中享有快速路径若列表第一个任务是 JustReturn则跳过截图与识别计算直接命中这就是不允许 JustReturn 位于非最后一项规则存在的原因——它会让后续任务永远没有识别机会。Stop动作返回NodeStatus::Interrupted直接结束整个流程。2.2 MatchTemplate 专属字段{ template: xxx.png, // 可选项模板图文件名字符串或字符串列表 // 默认 任务名.pngtemplate 及子文件夹下递归搜索 templThreshold: 0.8, // 可选项匹配得分阈值数字或数字列表默认 0.8 // 可根据日志查看实际得分 maskRange: [1, 255], // 可选项匹配时的灰度掩码范围 arrayint, 2 // 将不需要识别的部分涂黑灰度 0并设为 [1, 255] // 匹配时即忽略涂黑部分 colorScales: [ // method 为 HSVCount 或 RGBCount 时有效且必选 [ [23, 150, 40], // 结构 [[lower1, upper1], [lower2, upper2], ...] [25, 230, 150] ], // 内层为 int 时是灰度为 arrayint,3 时是三通道颜色 ... // method 决定其是 RGB 或 HSV ], // 中间层是颜色下限与上限最外层不同颜色范围的并集 colorWithClose: true, // 可选项数色前是否先做闭运算默认 true // 闭运算填补小黑点通常提升效果图中含文字建议 false pureColor: false, // 可选项默认 false // true 时忽略模板匹配得分完全依赖颜色匹配结果 nmsDistance: 0, // 可选项多结果去重半径像素默认 0 // 两个命中横纵坐标差都小于该值时只保留得分最高者 // 不填或 0 时按模板短边的一半取值 method: Ccoeff // 可选项模板匹配算法可以是列表默认 Ccoeff // - Ccoeff: 对颜色不敏感对应 cv::TM_CCOEFF_NORMED // - RGBCount: 对颜色敏感先按 colorScales 二值化 // 以 F1-score 计算 RGB 空间相似度再与 Ccoeff 结果点积 // - HSVCount: 类似 RGBCount颜色空间换为 HSV }generate_match_task_info 对这部分做了严格校验template数量必须与templThreshold、method数量一致单值会自动广播到所有模板templThreshold缺省时用基任务阈值补齐至模板个数colorScales支持灰度范围[lower, upper]与三通道颜色范围[[l0,l1,l2],[u0,u1,u2]]两种形式并保留对旧版灰度写法的兼容降级仅记录 debug 日志。另外Debug 构建ASST_DEBUG下使用RGBCount/HSVCount而未配置colorScales的任务会直接报错has empty color_scalesocrReplace中的非法正则会报has invalid regex——这是文档colorScales 必选约定的强约束实现。2.3 OcrDetect 专属字段{ text: [ 接管作战, 代理指挥 ], // 必选项要识别的文字任一匹配即识别到 ocrReplace: [ // 可选项针对常见识别错误进行替换支持正则 [ 千员, 干员 ], [ .击干员, 狙击干员 ] ], fullMatch: false, // 可选项是否全字匹配默认 false // false: 子串命中即可text: [开始] 能命中 开始行动 // true: 必须整段精确等于多一个字都不行 replaceFull: false, // 可选项ocrReplace 命中时是否替换整段文字默认 false // true 时只要整段命中任一规则整段替换为该规则替换值 isAscii: false, // 可选项识别内容是否为 ASCII 字符默认 false withoutDet: false // 可选项是否不使用检测模型默认 false }当algorithm为 OcrDetect 且withoutDet为true时以下字段额外生效{ useRaw: true, // 可选项是否使用原图匹配默认 true // false 时为灰度匹配 binThreshold: [140, 255] // 可选项二值化灰度阈值默认 [140, 255] // 灰度值不在范围内的像素视为背景 // 最终保留 [lower, upper] 区间像素作为文字前景 }generate_ocr_task_info 中可以看到text必须是字符串数组源码注释text 不允许为字符串必须是字符串数组其余字段全部按缺省则继承基任务的策略解析Debug 构建下若 OCR 任务既未写text也无基任务会给出has implicit empty text警告。2.4 JustReturn Input 与 FeatureMatch 专属字段algorithm为JustReturn、action为Input时{ inputText: A string text. // 必选项要输入的文字内容字符串 }algorithm为FeatureMatch时{ template: xxx.png, // 可选项模板图文件名字符串或列表默认 任务名.png count: 4, // 匹配特征点数量要求阈值默认 4 ratio: 0.6, // KNN 距离比值 [0 - 1.0]越大匹配越宽松默认 0.6 detector: SIFT // 特征点检测器SIFT / ORB / BRISK / KAZE / AKAZE / SURF默认 SIFT // SIFT: 计算复杂度高尺度/旋转不变效果最好 // ORB: 速度极快旋转不变无尺度不变性 // BRISK: 速度极快尺度/旋转不变 // KAZE: 适用于 2D/3D尺度/旋转不变 // AKAZE: 速度较快尺度/旋转不变 }generate_feature_match_task_info中detector通过get_feature_detector做字符串到枚举的映射非法值直接报错。三、表达式计算任务列表字段支持的操作符任务列表类型字段sub、next、onErrorNext、exceededNext、reduceOtherTimes支持表达式计算符号含义实例型任务FightReturnTo#单目虚任务#self#双目虚任务StartUpThemes#next*重复多个任务(ClickCornerAfterPRTSClickCorner)*10任务列表合并next 系列字段中同名任务只保留最靠前者AB^任务列表差在前者但不在后者顺序不变(AABC)^(ABD)结果为C运算符优先级#单目#双目*^。这套语法在源码中由 TaskDataSymbol 与TaskDataSymbolStream实现#被解析为一个特殊符号其后跟的none/self/back/next/sub/on_error_next/exceeded_next/reduce_other_times分别映射为SharpNone、SharpSelf、SharpBack、SharpNext、SharpSub、SharpOnErrorNext、SharpExceededNext、SharpReduceOtherTimes等枚举见 TaskDataSymbol.h 中sharp_types定义。解析后的符号流由 TaskData::compile_tasklist 统一展开虚任务按当前任务名与基任务字段递归解码最终列表再做去重next系列不允许重复sub/reduceOtherTimes允许allow_duplicate参数区分。四、特殊任务类型4.1 模板任务派生任务与型任务模板任务的核心可以理解为依据基任务修改字段的默认值。派生任务存在字段baseTask的任务即派生任务baseTask指向的任务称为基任务。对派生任务若是模板匹配任务字段template的默认值仍为任务名.png若algorithm与基任务不同则派生类参数不继承只继承TaskInfo定义的通用参数其余字段的默认值均为基任务对应字段。源码印证generate_raw_task_and_base 中读取到baseTask后以TaskDerivedType::BaseTask生成前缀为空generate_task_info先取出algorithm再按算法分发到generate_match_task_info/generate_ocr_task_info/generate_feature_match_task_info每个生成函数都以基任务对应对象为 default 参数逐个字段做缺省则继承。template的默认值逻辑则在generate_match_task_info中特判// 隐式 Template Task 时继承基任务 template其它情况默认 任务名.png return derived_type TaskDerivedType::Implicit ? default_ptr-templ_names : std::vector { std::string(name) .png };隐式型任务存在任务A且所有任务文件中均未直接定义形如BA的任务时BA即为隐式型任务A是其基任务。对隐式型任务任务列表字段的默认值为基任务对应字段直接加B前缀任务名以#开头则只加B前缀其余字段默认值均为基任务对应字段包括template即继承而非任务名.png。generate_raw_task_and_base中有一段专门的隐式生成逻辑当任务名含而右侧基任务存在时即使左侧从未定义也会以TaskDerivedType::Implicit生成该任务。显式型任务BA在任务文件中有直接定义哪怕只写了{}时即为显式型任务任务列表字段的默认值同样加B前缀#开头只加B若是模板匹配任务template默认值仍为任务名.png不继承基任务的模板图;algorithm与基任务不同时派生类参数不继承其余字段默认值为基任务对应字段。前缀拼接的实现是 TaskData::append_prefixif (task_name.starts_with(#)) { return std::string(task_prefix) std::string(task_name); // #back - B#back } return std::string(task_prefix) std::string(task_name); // N1 - BN14.2 虚任务#型任务虚任务即形如#{sharp_type}或B#{sharp_type}的任务{sharp_type}可以是none、self、back、next、sub、on_error_next、exceeded_next、reduce_other_times。可分为指令虚任务#none/#self/#back与字段虚任务#next等虚任务类型含义简单示例none空任务直接跳过¹A: {next: [#none, T1]}被解释为A: {next: [T1]}A#none T1被解释为T1self当前任务名A: {next: [#self]}中的#self被解释为AB: {next: [ABC#self]}中的ABC#self被解释为B²back#前面的任务名AB#back被解释为AB#back直接出现则会被跳过³next, sub 等#前任务名对应字段以next为例A#next被解释为Task.get(A)-next#next直接出现则会被跳过#none一般配合模板任务增加前缀的特性使用或用在字段baseTask中避免多文件继承不必要的字段。XXX#self与#self含义相同。当几个任务都有next: [ #back ]时T1T2T3代表依次执行T3、T2、T1。虚任务展开发生在任务列表编译阶段compile_tasklist中SharpSelf直接替换为当前任务名self_name而展开前的原始列表可通过Task.get_raw(name)查看——这也是文档示例中get与get_raw结果不同的原因。4.3 多文件任务如果后加载的任务文件例如外服tasks.json下称文件二中定义的任务在先加载的任务文件例如国服tasks.json下称文件一中也定义了同名任务那么文件二中任务没有baseTask字段直接继承文件一中同名任务的字段浅合并见lazy_parse中的逐 key 覆盖逻辑文件二中任务有baseTask字段不继承文件一中同名任务的字段而是直接覆盖。特别地在没有模板任务时可用baseTask: #none来避免继承不必要的字段lazy_parse中显式将baseTask #none的键擦除使其不参与继承。4.4 使用示例派生任务示例字段baseTaskReturn: { action: ClickSelf, next: [ Stop ] }, Return2: { baseTask: Return },则Return2任务的参数直接从Return继承实际上包含Return2: { algorithm: MatchTemplate, // 直接继承 template: Return2.png, // 任务名.png action: ClickSelf, // 直接继承 next: [ Stop ] // 直接继承与 Template Task 相比这里没有前缀 }型任务示例假设定义了包含以下参数的任务AA: { template: A.png, ..., next: [ N1, #back ] },若BA没有被直接定义隐式则其实际参数为BA: { template: A.png, ..., next: [ BN1, B#back ] }若BA有定义BA: {}显式则BA: { template: BA.png, ..., next: [ BN1, B#back ] }虚任务示例{ A: { next: [N1, N2] }, C: { next: [BA#next] }, Loading: { next: [#self, #next, #back] }, B: { next: [Other, BLoading] } }可以得到Task.get(C)-next { BN1, BN2 }; Task.get(BLoading)-next { BLoading, Other, B }; Task.get(Loading)-next { Loading }; Task.get_raw(BLoading)-next { B#self, B#next, B#back };4.5 注意事项运算符优先级导致的特例任务列表字段中定义的任务包含低优先级运算时实际结果可能不符预期与双目#的运算顺序{ A: { next: [N0] }, B: { next: [A#next] }, CA: { next: [N1] } }此时CB - next即CA#next为[ N1 ]而不是[ CN0 ]——因为双目#与同级先结合A#next取的是A自身的字段前缀只是贴在其上。与的运算顺序{ A: { next: [#back N0] }, BA: {} }Task.get(A)-next { N0 }; Task.get_raw(BA)-next { B#back N0 }; Task.get(BA)-next { B, N0 }; // 注意不是 [ B, BN0 ]反过来可以利用这个特性避免添加不必要的前缀例如只定义{ A: { next: [#none N0] } }五、运行时修改任务Task.lazy_parse()可以在运行时加载 JSON 任务配置文件合并规则与多文件任务完全相同baseTask存在则覆盖否则浅合并加载后调用clear_tasks()使已缓存的任务重新生成Task.set_task_base()可以修改任务的baseTask字段实现换基任务 换整套默认参数。set_task_base 的实现非常直接void asst::TaskData::set_task_base(const std::string task_name, std::string base_task_name) { m_json_all_tasks_info[task_name_view(task_name)][baseTask] std::move(base_task_name); clear_tasks(); }使用示例假设有任务配置文件如下{ A: { baseTask: A_default }, A_default: { next: [xxx] }, A_mode1: { next: [yyy] }, A_mode2: { next: [zzz] } }以下代码可以根据 mode 的值切换任务 A 的内容同时会连带改变所有依赖 A 的任务如 BAswitch (mode) { case 1: Task.set_task_base(A, A_mode1); // 基本上相当于用 A_mode1 的内容直接替换 A break; case 2: Task.set_task_base(A, A_mode2); break; default: Task.set_task_base(A, A_default); break; }注意clear_tasks()的源码注释它只清缓存已获取的任务指针内容不会自动更新——运行期修改对已经拿到的任务指针无效但不会崩溃需要重新get才能看到新值。六、Schema 校验与开发体验本项目为tasks.json配置了 JSON Schema 校验schema 文件为 docs/maa_tasks_schema.json。该 schema 采用patternProperties对除$开头外的任意顶层任务名做校验任务对象oneOf四种类型定义JustReturnTask/MatchTemplateTask/OcrDetectTask/FeatureMatchTask并对algorithm、action等字段给出了枚举约束与默认值描述例如action的默认值为DoNothing与运行时_default_task_info中的初始化一致。根据文档说明schema 的编辑器集成情况为Visual StudioMaaCore.vcxproj中已配置开箱即用但提示效果较为晦涩且有部分信息缺失Visual Studio Code.vscode/settings.json中已配置用 VSCode 打开项目文件夹即可使用提示效果较好文档还推荐使用 VSCode 并安装 Maa Pipeline Support 扩展实现高效编辑详见 VSCode 扩展教程。此外源码层还有第二道防线ASST_DEBUG构建下lazy_parse会执行syntax_checkTaskData.cpp按algorithm与action组合维护允许出现的字段白名单出现未知 key 即报错任务名中包含Doc的字段或存在xxx_Doc伴生键的字段可以豁免兜底策略非流程参数可以加_Doc注释字段放行。同时 Debug 模式还会遍历全部任务链检查 JustReturn 非末位、#selfLoadingText这类会导致无限隐式生成的写法并对隐式全屏 roi给出警告。这些检查在生产构建中不运行因此编辑器 schema 校验 运行时 Debug 检查是编写 tasks.json 时的两道主要防错手段。七、小结tasks.json协议由三块能力构成字段声明algorithm/action/roi/模板/OCR 等决定单个任务识别什么、做什么、表达式与特殊任务前缀模板、#虚任务、baseTask派生提供声明式复用、运行时可变性lazy_parse/set_task_base支持热切换流程。编写任务时建议遵循文档给出的最佳实践尽量填写roi缩小识别范围、优先直接识别最终要点击的位置而非依赖rectMove、注意next列表中 JustReturn 必须位于末位并用仓库提供的 schema 与 Debug 构建检查尽早暴露字段错误。【免费下载链接】MaaAssistantArknights《明日方舟》小助手全日常一键长草| A one-click tool for the daily tasks of Arknights, supporting all clients.项目地址: https://gitcode.com/GitHub_Trending/ma/MaaAssistantArknights创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考