Как отправлять клики и нажатия клавиш в неактивное окно игры

    Автоматизация фарма в нескольких окнах одновременно - сложная задача, особенно когда игра работает на Unity и не принимает команды из фона. Многие сталкиваются с тем, что стандартные методы Win32 API (SendInput, PostMessage) не срабатывают, если окно не в фокусе. Разберём, почему это происходит и какие существуют рабочие решения для многопоточного управления.

    Почему игра не реагирует на команды из неактивного окна

    Современные игры на Unity часто используют DirectInput или Raw Input для обработки ввода. Эти API получают данные напрямую от устройства (клавиатуры, мыши), минуя очереди сообщений Windows. Поэтому SendInput и PostMessage могут не работать - игра их просто игнорирует. Античит в данном случае отключён, но проблема кроется в архитектуре ввода.

    Методы отправки нажатий в неактивное окно

    1. Использование драйвера Interception

    Вы уже используете Interception для базовых нажатий. Этот драйвер перехватывает ввод на уровне ядра, эмулируя реальные события клавиатуры и мыши. Для неактивных окон он подходит, но требует, чтобы окно было активным в момент эмуляции. Решение - запускать каждое окно в отдельном потоке и программно переключать фокус между ними. Это замедляет процесс, но гарантирует, что игра получит сигнал.

    2. Эмуляция через Win32 API: SetFocus и SendMessage

    Попробуйте комбинацию: сначала вызовите SetForegroundWindow(hwnd), затем SendMessage(hwnd, WM_KEYDOWN, ...). Некоторые игры на Unity принимают сообщения, если окно находится на переднем плане. Для многопоточного фарма создайте цикл, который поочерёдно активирует каждое окно и отправляет команды. Недостаток - возможны задержки и мерцание.

    3. Использование библиотеки pyautogui с флагом фокуса

    В Python библиотека pyautogui может работать с окнами через pygetwindow. Но она тоже требует активного окна. Альтернатива - pydirectinput, которая специально создана для игр и использует SendInput с флагами, игнорирующими фокус. Однако на Unity это может не сработать.

    4. Внедрение в процесс игры (DLL-инъекция)

    Самый надёжный, но сложный метод - внедрить свою DLL в процесс игры и перехватывать функции ввода (например, GetAsyncKeyState или DirectInput::GetDeviceData). Тогда вы сможете программно вызывать нужные события, не затрагивая фокус окна. Этот подход используют китайские боты для 10-15 окон. Вам потребуется знание C++ и работы с памятью процесса.

    5. Использование виртуальных машин или sandbox

    Если игра не детектит виртуальное окружение, можно запускать каждое окно в отдельной виртуальной машине (VirtualBox, VMware). В каждой ВМ своя клавиатура и мышь, что снимает проблему фокуса. Минус - высокие требования к ресурсам.

    Пошаговая реализация для многопоточного фарма

    • Шаг 1. Получите дескрипторы окон (hwnd) для каждого экземпляра игры. Используйте FindWindow или EnumWindows.
    • Шаг 2. В каждом потоке запустите цикл: переключите фокус на нужное окно (SetForegroundWindow), отправьте команды через Interception или SendInput, затем переключитесь на следующее окно.
    • Шаг 3. Для синхронизации используйте threading.Lock, чтобы два потока не пытались активировать одно окно одновременно.
    • Шаг 4. Если игра требует зажатия клавиш (например, W), отправляйте WM_KEYDOWN и WM_KEYUP с задержкой.

    Рекомендации по выбору метода

    Если игра не проверяет активное окно - используйте Interception с переключением фокуса. Если нужна максимальная производительность - изучайте DLL-инъекцию. Для быстрого прототипа подойдёт pyautogui с pygetwindow. Помните: даже с отключённым античитом, слишком быстрые или неестественные действия могут вызвать подозрения у системы защиты игры.

    Часто задаваемые вопросы