一个 Windows 桌面小工具:看懂游戏窗口里的中文界面 → 决定该怎么做 → 用虚拟手柄把动作做出来, 并把整套业务循环写成一串可离线回放、可逐步验收的「原子流程」。
不注入进程、不读写游戏内存、不改游戏文件。全部通过「抓屏 + 系统自带 OCR + 虚拟手柄」完成。
面向重复性点击与切换类玩法的通用自动化助手,做三件事:
- 看:抓取目标窗口画面,用系统自带 OCR 识别中文(暂停菜单、标签页、列表项、左下角提示……),可选模板匹配辅助。
- 判断:把「看到了什么」变成证据(处于哪个模式、菜单是否打开、出现了什么弹窗、有没有失败提示……),再由判据决定成功/失败。
- 做:把判断结果变成动作(按键、摇杆手势、开关防火墙),交给虚拟手柄执行——动作只负责做,不自己判断成败。
三层分开带来的最大好处:整套流程可以离线回放。把抓好的截图按脚本喂进去,不碰游戏就能验证这串流程对不对。
| 能力 | 说明 |
|---|---|
| 纯外部覆盖层 | 分层透明窗口(点击穿透、不抢焦点、不注入),可在画面上实时画出识别区域与 OCR 词框,方便调参 |
| 中文 OCR 判定 | 系统 OCR + 多站点裁剪(整帧 / 标签条 / 列表焦点行 / 左下提示 / 中央弹窗),按“工作像素预算”统一缩放,跨分辨率稳定 |
| 抗 OCR 错字 | 关键词判据用字符命中计数(失败提示被读错字也能认出来)、焦点行用字符重合度匹配,不做整词相等 |
| 虚拟手柄动作 | 通过 ViGEm 虚拟手柄发按键与摇杆,窗口失焦也生效。必须安装 ViGEmBus 驱动(自检页有 [手柄驱动下载]):没装时程序启动就拦下并提示,因为没有任何替代输入方式 |
| 音频时机 | 回环采集系统输出音量,在“安静 → 突然变响”的那一刻触发关键动作 |
| 联网开关 | 两条独立规则:封存档只拦云存档/交易服务的出站(游戏不掉线);完全断网(F8)封全部出站=故意掉线。退出、崩溃残留有启动自愈(两条都会关掉),流程失败也确保恢复联网 |
| 原子流程引擎 | 流程写成 JSON:观察 / 动作 / 判据三层分离,支持重试、超时、超时重试、失败策略(跳过·继续·中止·回卷),步骤结果可作为后续分支条件 |
| 离线回放验收 | 自带帧脚本回放:按脚本推进画面与时间轴,不启动游戏就能跑完整轮流程并输出每一步证据 |
| 单文件分发 | 内置资源首次运行释放到用户数据目录,发布产物是一个 exe |
| 数据可清理 | 日志自动轮转;自检页显示各项占用并支持一键清理临时文件 |
- 到 Releases 页面下载
AutoPickup.exe; - 双击运行(首次运行会把内置资源释放到用户数据目录;以后换新版 exe,内置流程会自动更新,
你改过的那份会原样保留,新版另存为
shift_single.default.json); - 在自检页点「使用向导」,按提示确认环境(窗口、抓帧、输入层、OCR);
- 在参数页确认「进程名 / 窗口类」与目标程序一致,并按需微调识别区域;
- 在流程页设好轮数,点「开始班次」。
ViGEmBus 驱动是必需组件(自检页 [手柄驱动下载] 可打开官网,程序内不下载不安装)。没装时:启动即弹提示并退出、动作按钮全部禁用、班次无法开始 —— 因为键盘注入(
keybd_event)只能打进真实前台窗口,游戏在后台时无效,所以不存在“改用键盘”这条路。装好驱动后重启程序。
# 依赖:.NET 8 SDK(Windows)
git clone https://github.com/LtcYGL/AutoPickup.git
cd AutoPickup
dotnet build # 开发构建
pwsh -File publish.ps1 # 产出 dist\AutoPickup.exe(单文件)
pwsh -File publish.ps1 -SelfContained # 自包含单文件(体积大,但无需装 .NET)| 设置 | 取值 | 为什么 |
|---|---|---|
| 显示模式 | 窗口化 / 无边框窗口 | 独占全屏下识别框覆盖层不显示,抓帧也可能拿不到画面 |
| 失焦暂停 | 否 | 开着的话你一切到别的窗口游戏就停住,整轮卡死 |
| 失焦静音 | 否 | 开着的话游戏不在前台时完全不出声,「下云」cue 就抓不到(表现是一直等到 240 秒超时补封) |
| 音频输出 | 不用管(默认按进程抓) | 默认只抓游戏进程(含子进程)的声音:前台看片、看网页视频都不影响判据,游戏崩溃重启会自动重挂。只有取消参数页「3 音频 · 跟随游戏进程」时,才按「捕获设备」抓整台设备的混音(那时是启动时绑定一次、之后不跟随) |
| 线上出生点 | 室内 / 公寓 | 进战局即安全,不会被其他玩家干扰 |
失焦暂停 / 失焦静音这两项,线下(故事模式)与线上(GTA 在线模式)的设置页是分开的,两边都要设成「否」。 踩过的坑:重装 Rockstar Social Club 会把游戏设置重置回默认,这两项跟着变回「是」,于是下云 cue 再也抓不到 —— 抓不到 cue 时先回来查这两项,再怀疑程序。
- 准备:已有 CEO 办公室 + 特种货物仓库(想卡几个仓就备几个,数量和容量都无所谓)。 首次上机先用流程页的 [进入线上] / [回到故事] 各单独跑一遍,确认动作与识别正常。
- 派遣:去仓库让员工发货 —— 特种货物仓库
$7500/次、机库$25000/次,要卡几个仓就去几个仓各自派满; 所有派遣必须落在同一个取货周期内(游戏内两天 = 现实 48 分钟)。 - 就位:把线上出生点设成室内,然后退出到线下(故事模式)。
- 开卡:以最后一个员工出发的时间为起点,在流程页把「启动前等待」设为 48 分钟 (为稳妥建议 50–55 分钟),到点后点 [开始班次]。
- 容量参考:大仓 111 箱通常 85–95 轮拿满;机库满仓 50 箱一般 40+ 轮。 仓库容量不同不影响,不会造成存档冲突或错位。
- 自检页:环境状态灯、只读诊断、联网控制、数据占用与清理。
- 参数页:全部可调参数(识别区域百分比、OCR 缩放、阈值、等待时间、热键……),改完即时生效。
- 流程页:模式切换测试、封网开关、班次设置与启停。运行日志在下方,可折叠。
| 热键 | 作用 |
|---|---|
| F6 | 显示/隐藏识别框(区域可视化 + OCR 词框) |
| F7 | 封云存档 开/关(只拦存档服务,游戏不掉线) |
| F8 | 完全断网 开/关(故意掉线:封全部出站 TCP+UDP;与封存档独立,可同时开) |
| F9 | 结束游戏进程(等效任务管理器强杀,游戏来不及写存档) |
热键可在参数页修改,全局生效(目标程序在前台也能按)。
流程文件是普通 JSON(放在 flows/),一个步骤长这样:
- 观察(纯读,不按键):
mode/menuopen/dialog/toast/selectedtab/focusrow/text - 动作(只做,不自验):
tap/gesture/menu/tab/navigate/firewall/waitcue/waitmode/sleep - 判据(决定成败):
eq/ne/in/nin/gt/ge/lt/le/truthy/falsy/contains/like
一条真实的业务循环就是这些原子的拼接:进线上 → 等到关键音频时刻立刻封锁 → 确认到达 → 验证出现失败提示 → 回故事 → 恢复联网。 手势失败会自动改走暂停菜单流程(与手动操作习惯一致)。
AutoPickup.exe --run-flow flows\shift_single.json --replay replays\shift\script.json回放脚本给每帧标一个停留时长,并按动作定义“触发某动作就切到哪一帧”,于是观察不推进、动作推进, 整条流程能在几秒内跑完并输出每一步的证据轨迹。
仓库自带回归脚本,一条命令跑完所有流程:
pwsh -File run_replay_regress.ps1首次运行会在 %LOCALAPPDATA%\AutoPickup\ 下建立:
| 目录 / 文件 | 内容 | 会不会增长 |
|---|---|---|
settings.json / ui.json |
参数与界面布局 | 否 |
flows/ |
流程定义(可自行修改) | 否 |
native/ |
首次运行释放的原生库 | 否 |
logs/ |
运行日志(超过 3MB 自动轮转,只留 1 份历史) | 会 |
frames/ samples/ diag/ |
采帧、样本、诊断输出(都需手动触发才产生) | 会 |
自检页 →「数据与占用」 会显示各项占用,并提供「清理临时文件」一键清理(只删会增长的三类,不动参数、流程与模板)。
换新版 exe 时的资源更新规则:
| 资源 | 规则 |
|---|---|
templates/ |
永不覆盖:你替换或新增的模板一直有效 |
flows/ |
跟着 exe 更新;你改过的文件原样保留,内置新版另存为 xxx.default.json。从旧版本第一次升级时,改动前的副本留成 xxx.bak |
native/ |
与内嵌版本不一致时直接更新 |
日志开头会打印一行 原子流程已载入: …(N 步,sha256 xxxxxxxx),出现「运行结果和预期不一样」时先看这行,
确认跑的是哪一版流程,再去查别的。
AutoPickup.csproj 项目文件
Program.cs 入口 + 命令行诊断工具(--run-flow / --profile-read / --run-shift …)
AppRuntime.cs 组件组装
Config/ 参数模型、持久化、参数页数据源
Core/
Capture/ 窗口抓帧(PrintWindow 优先,屏幕拷贝兜底)
Vision/ 预处理、识别站点、标签条与焦点行读取、模板匹配
Ocr/ 系统 OCR 封装(含中文语言包探测)
Input/ 输入层:虚拟手柄(必需)/ 空实现(缺驱动时的占位)
Audio/ 回环音量与“安静→响亮”时机检测
Net/ 防火墙规则(两条独立规则)
Flow/ 原子流程引擎:观察 / 动作 / 判据 / 宿主 / 回放
Menus/ 文本模糊匹配(菜单名/列表项的容错比较)
Native/ Win32 与原生库封装
Jobs/ 班次编排(重试策略、安全收尾)
Ui/ WinForms 界面:主窗口、覆盖层、向导、参数页
flows/ 流程定义(JSON):shift_single 班次 / go_online 进线上 / return_story 回线下
docs/ 架构说明
publish.ps1 一键打包单文件 exe
run_replay_regress.ps1 离线回放回归
本项目的实现思路与关键组件,受以下开源项目与资料启发或直接依赖:
| 项目 / 组件 | 用途 | 说明 |
|---|---|---|
| gtaz | 前身与主要参考 | 本项目的业务流程(取货循环、封锁时机、模式切换)源自这个开源项目的思路;本仓库是它在「识别与流程结构」上的重写与扩展 |
| ViGEmBus / ViGEmClient | 必需组件:虚拟手柄 | 让工具能在窗口失焦时依然按键(BSD-3-Clause;仓库内含 ViGEmClient.dll)。没装驱动无法使用(程序启动会拦下) |
| NAudio | 音频采集 | WASAPI 回环采集系统输出音量,用于关键时刻判定(MIT) |
| Windows.Media.Ocr | 中文识别 | 系统自带 OCR,无需外部模型,离线可用 |
| .NET 8 / Windows Forms | 运行时与界面 | 单文件发布、分层透明覆盖层 |
| Windows OCR 语言包 | 语言支持 | 需系统已安装中文识别语言包(程序会检测并提示) |
本仓库不包含任何游戏截图、美术资源或模板图片——它们属于各自权利人。 如需启用可选的模板匹配能力,请自行截图并裁剪到
assets/templates/(会随 exe 内嵌)。
- 需求、验收与产品取向:LtcYGL(本仓库所有者)。
- 代码实现:绝大部分代码由 AI 助手(DeepSeek)编写——包括识别管线、原子流程引擎、离线回放、界面与打包脚本。 全过程由 LtcYGL 提出需求、在真实环境中反复实测、给出反馈与取舍,AI 负责实现、修正与验证。
- 因此本仓库会呈现「AI 主导实现 + 人类主导验收」的特征,特此说明。
- 本项目仅用于学习与自动化技术研究,不注入、不修改、不绕过任何目标软件的文件与内存。
- 请在你自己拥有或已获授权的环境中、并遵守目标软件服务条款的前提下使用。
- 自动化操作可能违反部分在线服务的用户协议,由此产生的一切后果由使用者自行承担。
- 作者不对因使用本工具造成的账号风险、数据丢失或其它损失负责。
- 本仓库不含任何游戏素材;相关商标与内容归其各自权利人所有。
{ "id": "wait_story", "title": "等待到达故事", // 日志里显示的中文短标签 "action": { "op": "waitmode", "target": "story", "ms": 300 }, "expect": [ "fact:mode_reached eq true" ], // 判据 "onFail": "abort" // 失败策略 }