news 2026/9/13 10:28:01

MaaAssistantArknights 任务流程协议详解:resource/tasks 字段、虚任务表达式与 Schema 校验

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
MaaAssistantArknights 任务流程协议详解:resource/tasks 字段、虚任务表达式与 Schema 校验

MaaAssistantArknights 任务流程协议详解:resource/tasks 字段、虚任务表达式与 Schema 校验

【免费下载链接】MaaAssistantArknights《明日方舟》小助手,全日常一键长草!| A one-click tool for the daily tasks of Arknights, supporting all clients.项目地址: https://gitcode.com/GitHub_Trending/ma/MaaAssistantArknights

本文详解 MaaAssistantArknights(Maa)中resource/tasks任务配置的完整协议:全部字段含义与默认值、四类识别算法的专用参数、任务列表表达式(@#*+^)的运算规则、模板任务与虚任务的继承机制,以及如何结合 JSON Schema 在编辑器中做配置校验。读完后你将能够读懂乃至独立编写 Maa 的tasks.json任务流,理解next/sub/exceededNext等控制流字段的展开逻辑,并在执行中通过lazy_parseset_task_base动态改写任务行为。

一、任务配置的基本模型

Maa 的自动任务由resource/tasks目录下的 JSON 文件定义:每个任务是一个以任务名(如"TaskName")为键的对象,运行时按“识别(algorithm)→ 动作(action)→ 流转(sub / next / exceededNext / onErrorNext)”的顺序推进。整份任务图的骨架可以概括为:

{ "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,对应 inputText "sub": ["SubTaskName1", "SubTaskName2"], // 选填,子任务,不推荐使用。会在执行完目前任务后,依序执行每一个子任务 // 可以套娃(子任务再套子任务),但要注意不要写出无穷循环 "subErrorIgnored": true, // 选填,是否忽略子任务的错误,不填写默认 false // false 时子任务出错则不继续执行后续任务;true 时子任务出错没有影响 "next": ["OtherTaskName1", "OtherTaskName2"], // 选填,执行完目前任务和 sub 任务后,下一个要执行的任务 // 会从前往后依序辨识,执行第一个比对成功的 // 不填写默认执行完目前任务直接停止 // 对相同任务,第一次辨识后第二次就不再辨识: // "next": [ "A", "B", "A", "A" ] -> "next": [ "A", "B" ] // 不允许 JustReturn 型任务位于非最后一项 "maxTimes": 10, // 选填,该任务最大执行次数,不填写时默认为无穷大 // 达到最大次数后,若存在 exceededNext 字段则执行 exceededNext;否则直接任务停止 "exceededNext": ["OtherTaskName1", "OtherTaskName2"], // 选填,达到最大执行次数后要执行的任务 // 不填写时达到上限则停止;填写后就执行这里的,而不是 next 里的 "onErrorNext": ["OtherTaskName1", "OtherTaskName2"], // 选填,执行出错时,后续要执行的任务 "preDelay": 1000, // 选填,辨识到后延迟多久才执行 action,单位毫秒;默认 0 "postDelay": 1000, // 选填,action 执行完后延迟多久才去辨识 next,单位毫秒;默认 0 "roi": [0, 0, 1280, 720], // 选填,辨识范围,格式 [ x, y, width, height ] // 以 1280 * 720 为基准自动缩放;不填写时默认 [ 0, 0, 1280, 720 ] // 尽量填写,减小辨识范围可以减少效能消耗,加快辨识速度 "cache": false, // 选填,是否使用快取,默认 false // 开启后第一次辨识到目标时,以后永远只在第一次辨识到的位置进行辨识,可大幅节省效能 // 仅适用于待辨识目标位置完全不会变的任务 "rectMove": [0, 0, 0, 0], // 选填,辨识后的目标移动,不建议使用。以 1280 * 720 为基准自动缩放 // 例如辨识到 A,但实际要点 A 下方 10 像素 5*2 区域内的某位置, // 可填 [ 0, 10, 5, 2 ];可以的话尽量直接辨识要点击的位置 // 当 action 为 Swipe 时有效且必填,表示滑动终点 "reduceOtherTimes": ["OtherTaskName1", "OtherTaskName2"], // 选填,执行后减少其他任务的执行计数 // 例如执行了使用理智药,说明上一次点蓝色开始按钮没生效,所以蓝色开始要 -1 "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]、[3] 分别填 37, 1 "highResolutionSwipeFix": false, // 选填,是否启用高解析度滑动修复,默认 false // 现阶段应只有关卡导航未使用 unity 滑动方式时需要开启 } }

注意:JSON 文件本身不支持注释,上述行内注释仅供理解参考,实际编写tasks.json时请勿保留。

从源码看任务的加载与展开

上述配置最终由 TaskData 单例解析。从源码结构看,TaskData内部维护了三层映射(见 TaskData.h):

  • m_json_all_tasks_info:原始的 JSON 任务定义;
  • m_raw_all_tasks_info:未展开虚任务的任务信息;
  • m_all_tasks_info:已展开虚任务、可直接执行的任务信息。

对外提供get()(取已展开任务)、load()/lazy_parse()(加载配置)、set_task_base()(修改baseTask)等接口,并以inline static auto& Task = TaskData::get_instance();暴露为全局Task句柄——这正是后文“执行中更改任务”一节中示例代码里Task.get(...)的来源。

二、四类识别算法的专用字段

任务中algorithm之外的字段按算法分属不同“衍生类别参数”。这与 docs/maa_tasks_schema.json 中的oneOf结构(JustReturnTask/MatchTemplateTask/OcrDetectTask/FeatureMatchTask四种定义均allOf引用公共的BaseTask)一一对应。

MatchTemplate:模板比对

以下字段仅当algorithmMatchTemplate(缺省值)时有效:

"template": "xxx.png", // 要比对的文件名,可为字串或字串列表,默认 "任务名称.png" // 範本圖可放在 template 及其子資料夾下,載入時遞迴搜尋 "templThreshold": 0.8, // 比對得分門檻,超過才認為辨識到;可為數字或數字列表,預設 0.8 "maskRange": [1, 255], // 灰階遮罩範圍,如將圖片不需辨識部分塗黑(灰階 0)並設 [1, 255] 即可忽略塗黑處 "method": "Ccoeff", // 範本比對演算法,可為列表,預設 Ccoeff // - Ccoeff: 對顏色不敏感,對應 cv::TM_CCOEFF_NORMED // - RGBCount: 依 colorScales 二值化後以 F1-score 計算 RGB 空間相似度,再與 Ccoeff 結果內積 // - HSVCount: 類似 RGBCount,顏色空間換為 HSV "nmsDistance": 0, // 多結果去重(NMS)半徑,單位像素;兩個命中位置橫縱座標差都小於該值時只留最高分, // 不填或 0 時按範本短邊的一半取值

methodHSVCountRGBCount时还需注意:

"colorScales": [ // 数色遮罩范围,此两种 method 下必填 [ [23, 150, 40], // 结构 [[lower1, upper1], [lower2, upper2], ...] [25, 230, 150] ] // 内层为 int 时是灰階,为 array<int,3> 时是三通道颜色; ... // 最外层代表不同颜色范围,待辨识区域为它们对应遮罩的联集 ], "colorWithClose": true, // 数色时是否先做闭运算处理遮罩(默认 true) // 闭运算可填补小黑点提高效果,但图中包含文字时建议 false "pureColor": false, // 为 true 时忽略範本比對得分,完全依赖颜色比對结果(默认 false) // 适用于颜色特征明显但模板比对效果不佳的场景,建议相应提高 templThreshold

OcrDetect:文字辨识

以下字段仅当algorithmOcrDetect时有效:

"text": [ "接管作戰", "代理指揮" ], // 必填项,要辨识的文字,任一匹配成功即认为辨识到 "ocrReplace": [ // 选填,针对常见辨识错误进行替换(支援正規表示式) [ "千員", "幹員" ], [ ".+擊幹員", "狙擊幹員" ] ], "fullMatch": false, // 是否全字比對(不能多字),預設 false // false 时子串即可:text 为 "开始",实际辨识到 "开始行动" 也算成功 "replaceFull": false, // ocrReplace 命中时是否替换整段文字,預設 false "withoutDet": false, // 是否不使用检测模型,預設 false "isAscii": false, // 要辨识的文字是否为 ASCII 字符,預設 false

withoutDettrue时额外可用:

"useRaw": true, // 是否使用原圖比對,預設 true;false 時為灰階比對 "binThreshold": [140, 255], // 二值化灰階門檻值,預設 [140, 255] // 灰階值不在範圍內的像素視為背景,最終保留 [lower, upper] 區間像素作為文字前景

注:docs/maa_tasks_schema.json 中OcrDetectTaskrequired["algorithm", "text"],并在useRaw/binThreshold的描述中标注了生效条件,可作为编辑器校验的依据。

JustReturn + Input:纯文字输入

algorithmJustReturnactionInput时:

"inputText": "A string text." // 必填项,要输入的文字內容

Schema 中该组合通过条件校验强制inputText必填(BaseTaskallOf分支之一)。

FeatureMatch:特征点比对

以下字段仅当algorithmFeatureMatch时有效:

"template": "xxx.png", // 要比對的圖片檔案名稱,預設 "任務名稱.png" "count": 4, // 比對特徵點的數量要求(門檻值),預設 4 "ratio": 0.6, // KNN 比對演算法的距離比值 [0 - 1.0],越大越寬鬆,預設 0.6 "detector": "SIFT", // 特徵點檢測器,預設 SIFT // 可選:SIFT / ORB / BRISK / KAZE / AKAZE / SURF // SIFT:複雜度高,具尺度、旋轉不變性,效果最好 // ORB:速度極快,具旋轉不變性,無尺度不變性 // BRISK:速度快,具尺度、旋轉不變性 // KAZE:適用於 2D/3D 圖像,具尺度、旋轉不變性 // AKAZE:速度較快,具尺度、旋轉不變性

三、任务列表表达式

任务列表类型字段(subnextonErrorNextexceededNextreduceOtherTimes)的值支持表达式计算:

符号含义实例
@@型任务Fight@ReturnTo
#(一元)虚任务#self
#(二元)虚任务StartUpThemes#next
*重复多个任务(ClickCornerAfterPRTS+ClickCorner)*10
+任务列表合并(在 next 系列字段中同名任务只保留最靠前者)A+B
^任务列表差(在前者但不在后者,顺序不变)(A+A+B+C)^(A+B+D)(结果为C

运算符优先级为:#(一元) >@=#(二元) >*>+=^

这一套词法在源码中由 TaskDataSymbol 实现:其Type枚举(AtSharpMulAddSub(即^)、LParen/RParen等)与symbol_repr_to_type映射表完整对应上表中的各符号;虚任务关键字则以SharpSub/SharpNext/SharpSelf/SharpBack/SharpNone等独立词元出现(src/MaaCore/Config/TaskData/TaskDataSymbol.h#L44-L65),说明表达式在解析阶段就被切分为带类型的符号流,再由TaskDatacompile_raw_tasklist/compile_tasklist两阶段编译为最终任务列表。

四、特殊任务类型

4.1 模板任务

模板任务包括衍生任务与@型任务,其核心可理解为根据父任务修改字段的默认值

衍生任务(baseTask)

存在字段baseTask的任务即衍生任务,baseTask对应的任务称为其父任务。规则:

  1. 若是模板比对任务,字段template的默认值仍为"任务名称.png"
  2. 若字段algorithm与父任务不同,则衍生类别参数不继承(只继承TaskInfo定义的参数);
  3. 其余字段的默认值均为父任务对应字段
隐式@型任务

存在任务"A"且所有任务文件中均未直接定义的形如"B@A"的任务即隐式@型任务,"A"称其父任务。规则:

  1. 任务列表类型字段(subnextonErrorNextexceededNextreduceOtherTimes)的默认值为父任务对应字段直接增加B@前缀(如遇任务名称开头为#则增加B前缀);
  2. 其余字段的默认值均为父任务对应字段(包括template)。
显式@型任务

存在任务"A"且任务文件中直接定义了"B@A"时即显式@型任务。规则:

  1. 任务列表类型字段默认值为父任务对应字段增加B@前缀(遇#开头增加B前缀);
  2. 若是模板比对任务,template默认值仍为"任务名称.png"
  3. algorithm与父任务不同,衍生类别参数不继承;
  4. 其余字段默认值为父任务对应字段。

4.2 虚任务(#型任务)

虚任务形如"#{sharp_type}""B#{sharp_type}",其中{sharp_type}可为noneselfbacknextsubon_error_nextexceeded_nextreduce_other_times,可分指令虚任务#none/#self/#back)与字段虚任务#next等):

虚任务类型含义简单范例
none空任务,直接跳过"A": {"next": ["#none", "T1"]}被视为"A": {"next": ["T1"]}"A#none + T1"被视为"T1"
self目前任务名称"A": {"next": ["#self"]}中的"#self"被视为"A""B": {"next": ["A@B@C#self"]}中的"A@B@C#self"被视为"B"
back#前面的任务名称"A@B#back"被视为"A@B""#back"直接出现则被跳过
nextsub#前任务名称对应字段next为例:"A#next"被视为Task.get("A")->next"#next"直接出现则被跳过

三个值得记住的备注:

  1. "#none"一般配合模板任务增加前缀的特性使用,或用在字段baseTask中避免多文件继承不必要的字段;
  2. "XXX#self""#self"含义相同;
  3. 当几个任务都有"next": [ "#back" ]时,"T1@T2@T3"代表依序执行T3T2T1(层层回退到父任务)。

4.3 多文件任务

若后载入的任务文件(例如外服tasks.json,下称文件二)中定义了先载入文件(例如国服tasks.json,下称文件一)中已存在的同名任务:

  • 文件二的任务没有baseTask字段:直接继承文件一中同名任务的字段;
  • 文件二的任务baseTask字段:不继承文件一,而是直接覆盖。特别地,在没有模板任务时可用"baseTask": "#none"避免继承不必要的字段。

4.4 使用示例

衍生任务(baseTask。假设:

"Return": { "action": "ClickSelf", "next": [ "Stop" ] }, "Return2": { "baseTask": "Return" }

"Return2"实际展开为:

"Return2": { "algorithm": "MatchTemplate", // 直接继承 "template": "Return2.png", // "任务名称.png" "action": "ClickSelf", // 直接继承 "next": [ "Stop" ] // 直接继承,与模板任务相比这里没有前缀 }

@型任务。假设任务"A"含:

"A": { "template": "A.png", "next": [ "N1", "#back" ] }

"B@A"未被直接定义,其实际参数为:

"B@A": { "template": "A.png", "next": [ "B@N1", "B#back" ] }

"B@A"有定义"B@A": {},则实际参数为:

"B@A": { "template": "B@A.png", "next": [ "B@N1", "B#back" ] }

虚任务。给定:

{ "A": { "next": ["N1", "N2"] }, "C": { "next": ["B@A#next"] }, "Loading": { "next": ["#self", "#next", "#back"] }, "B": { "next": ["Other", "B@Loading"] } }

可得到:

Task.get("C")->next = { "B@N1", "B@N2" }; Task.get("B@Loading")->next = { "B@Loading", "Other", "B" }; Task.get("Loading")->next = { "Loading" }; Task.get_raw("B@Loading")->next = { "B#self", "B#next", "B#back" };

对应源码中Task.get()返回已展开任务(m_all_tasks_info),而展开前的原始列表仍保留在m_raw_all_tasks_info中——这正是示例里get_rawget结果不同的原因。

4.5 注意事项(表达式优先级陷阱)

若任务列表字段中定义了包含低优先级运算的任务,实际结果可能不符预期:

  1. @与二元#的运算顺序特例

    { "A": { "next": ["N0"] }, "B": { "next": ["A#next"] }, "C@A": { "next": ["N1"] } }

    此时"C@B" -> next(即C@A#next)为[ "N1" ]而不是[ "C@N0" ]

  2. @+的运算顺序特例

    { "A": { "next": ["#back + N0"] }, "B@A": {} }

    此时:

    Task.get("A")->next = { "N0" }; Task.get_raw("B@A")->next = { "B#back + N0" }; Task.get("B@A")->next = { "B", "N0" }; // 注意不是 [ "B", "B@N0" ]

    事实上可反向利用该特性避免增加不必要的前缀,只需定义:

    { "A": { "next": ["#none + N0"] } }

五、执行中更改任务

  • Task.lazy_parse()可在执行中载入 JSON 任务配置文件,规则与上文多文件任务一节相同;
  • Task.set_task_base()可修改任务的baseTask字段。

两者的 C++ 声明见 TaskData.h 中的bool lazy_parse(const json::value& json)void set_task_base(const std::string& task_name, std::string base_task_name)

示例:按模式切换任务基类

假设有任务配置文件:

{ "A": { "baseTask": "A_default" }, "A_default": { "next": ["xxx"] }, "A_mode1": { "next": ["yyy"] }, "A_mode2": { "next": ["zzz"] } }

以下代码可根据mode的值改变任务"A",同时会改变其他依赖"A"的任务(例如"B@A"):

switch (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; }

该机制在仓库中有大量真实用例:例如src/MaaCore/Task/Roguelike/RoguelikeConfig.cpp中通过Task.set_task_base(m_theme + "@Roguelike@Stages", m_theme + "@Roguelike@Stages_default")切换主题默认阶段,src/MaaCore/Task/Roguelike/BlackFlow/BlackFlowRoutingTaskPlugin.cpp中则按路线状态在多个BlackFlow@Roguelike@...基类之间来回切换,实现“同一入口任务名、运行时换行为”的效果。

六、Schema 校验

本仓库为tasks.json配置了 JSON Schema 校验,Schema 文件为 docs/maa_tasks_schema.json。其要点:

  • 顶层patternProperties^(?!\$)匹配所有任务键,每个任务对象通过oneOf匹配四种算法任务定义之一;
  • BaseTask中用if/then条件校验实现了字段联动约束:actionClickRectspecificRect必填;actionSwipespecificRectrectMove均必填;algorithmJustReturnactionInputinputText必填;
  • MatchTemplateTasktemplThreshold支持数组且注明“多模板时阈值数量需与模板数量一致”;OcrDetectTaskalgorithmtext列为必填。

Visual Studio

MaaCore.vcxproj中已对其完成设置,内建功能开箱即用。提示效果较为晦涩,且有部分信息缺失。

Visual Studio Code

.vscode/settings.json中已对其完成设置,使用 Visual Studio Code 打开该项目文件夹即可使用,提示效果较好。

推荐配合 Maa Pipeline Support 扩展(提供模板预览、next跳转、任务引用查询、任务表达式展开计算等功能)实现高效编辑,扩展教程见 docs/zh-tw/develop/vsc-ext-tutorial.md。

七、编写任务时的实践建议

结合本文各节,日常编写tasks.json时可遵循:

  1. 控制流优先用next表达sub不推荐(仅用于必须串行且与主流程解耦的场合),next支持“取第一个识别成功者”的分支语义;
  2. 缩小roi:所有坐标字段以 1280×720 为基准自动缩放,填写更小的roi能减少性能消耗并加快识别;
  3. cache只给固定位置目标用:目标位置会变的任务保持默认false
  4. 善用@型任务与虚任务替代重复配置,但注意第四节列出的优先级特例;
  5. 多文件(国服/外服)维护时:外服覆盖用baseTask显式声明,无父类时用"baseTask": "#none"切断继承;
  6. 运行时动态行为set_task_base/lazy_parse实现,避免为每个分支复制整份任务图。

【免费下载链接】MaaAssistantArknights《明日方舟》小助手,全日常一键长草!| A one-click tool for the daily tasks of Arknights, supporting all clients.项目地址: https://gitcode.com/GitHub_Trending/ma/MaaAssistantArknights

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/13 10:27:50

Apriltag坐标系方向可视化:原理、Python实现与避坑指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/13 10:27:07

多目标进化算法实战:NSGA-II与帕累托前沿解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/13 10:26:38

统一接入钉钉、飞书、企业微信:多平台AI机器人中枢开源实现

坦白讲&#xff0c;这两年团队协作最大的痛点不是"没有 AI"&#xff0c;而是"AI 散落在一堆群里"。技术群里拉了机器人&#xff0c;老板在钉钉上也想用同一个智能助手&#xff0c;客户那边用飞书&#xff0c;合作伙伴只认企业微信。真要做&#xff0c;每个…

作者头像 李华
网站建设 2026/9/13 10:21:38

西门子PLC电梯控制系统设计与实现

1. 项目背景与硬件架构设计这个电梯控制系统项目采用了西门子S7-1200 PLC作为核心控制器&#xff0c;搭配WinCC RT Professional V14实现可视化监控。在实际工业现场&#xff0c;这种架构常见于中大型商业建筑的电梯群控场景。我去年参与过一个医院门诊楼的电梯改造项目&#x…

作者头像 李华
网站建设 2026/9/13 10:20:05

UWB NLOS识别:基于CNN的CIR信号分类方法

简介&#xff1a;本资源是一套完整的超宽带&#xff08;UWB&#xff09;非视距&#xff08;NLOS&#xff09;信号分类实战项目&#xff0c;面向计算机、人工智能、通信工程等专业学生及初入深度学习领域的开发者&#xff0c;解决UWB定位中因障碍物导致的NLOS误差识别与分类难题…

作者头像 李华
网站建设 2026/9/13 10:19:51

大模型技术解析:从Transformer架构到训练部署实战

1. 大模型技术全景概览大模型技术正在重塑整个AI行业的发展轨迹&#xff0c;作为一名长期奋战在一线的技术从业者&#xff0c;我见证了从早期RNN到如今Transformer架构的演进历程。当前主流大模型普遍基于Transformer架构&#xff0c;参数量从数十亿到数千亿不等&#xff0c;其…

作者头像 李华