Как подружить Steam, Unity и контроллеры
Приветствую разработчики игр. ДНО снова выходит на связь. Речь пойдет о том, как подружить Unity и Steam в контексте устройств ввода. Сейчас у меня на руках есть такие контроллеры как: Steam Controller, XBox360, XBoxOne, PS4 и PS5. И задача стояла - запустить их все через Steam Input. Смотри как это сделать, даже без аккаунта разработчика.
Информация из документации Steam
«Система ввода Steam» (Steam Input) — это общий термин для всех устройств, программного обеспечения и настроек утилит, которые Steam использует для взаимодействия с играми.
Интерфейс настройки системы ввода Steam (Steam Input Configurator, SIC) встроен в клиент Steam и находится между игроком и игрой/приложением. Интерфейс ввода получает сигналы от устройства ввода и переводит эти данные должным образом — в зависимости от того, какие настройки установлены у игрока, прежде чем передать их игре.
API ввода Steam — программный интерфейс, который разработчики используют, чтобы напрямую общаться с интерфейсом ввода SIC в режиме встроенной поддержки. API контроллера не обязателен для работы режима совместимости.
Более полную информацию, вы можете найти здесь
К сожалению, для Unity нет встроенной поддержки, поэтому для связи нужно использовать сторонние решения. На данный момент есть два: Steamworks.NET и Facepunch.Steamworks.
Подготовка файла с внутриигровыми действиями (IGA)
Нужно подготовить конфигурацию действий, которые мы будем использовать в игре. По сути это инструкции событий для устройства ввода. А сам игрок сможет перенастроить эти действия в Steam.
Создадим файл вручную. Внутри папки Steam создаем папку "controller_config" (например, C:/Program Files (x86)/Steam/controller_config) и там создаем файл game_actions_480.vdf
Где 480 - идентификатор приложения (AppID). В данном случае 480 - идентификатор игры SpaceWar (приложение-образец с API Steamworks)
Если у вас уже есть страница игры, то вместо 480 используйте свой AppID.
Я специально убрал всё лишнее, оставив лишь одно действие.
GameControls - название группы действий, которое мы будем обрабатывать из кода. # Set_GameControls - ссылка для локализации настроек контроллера игрока.
Jump - название действия, которое мы будем обрабатывать из кода. Соответственно # Action_Jump ссылается на значение, которое будет видеть игрок, изменяя событие на другую кнопку.
Чтобы попробовать и понять как это работает, нам этого хватит. Более подробно о IGA
Facepunch.Steamworks
Начнем с более “дружелюбного” решения от Facepunch Studios (Rust и Garry's Mod). Установка простая: скачать и распаковать в директорию проекта.
Вызовы инициализации, обновления и завершения:
Steamworks.SteamClient.Init(480);
Steamworks.SteamClient.RunCallbacks();
Steamworks.SteamClient.Shutdown();
Запустив проект в Unity, после инициализации Facepunch.Steamworks подтянет файл с внутриигровыми действиями (IGA) game_actions_480.vdf. Запустится в Steam SpaceWar. И если у вас подключен контроллер, то вы сможете назначить действие Jump на одну из кнопок.
А теперь давай поймаем событие Jump.
Немного приколов и важных штук!
При подключении контроллера, после запуска SpaceWar, вы можете в Unity получать ошибку:
<RI.Hid> Failed to get preparsed data: Операция успешно завершена.
Если остановить игру, то вы увидите, что SpaceWar по прежнему запущен. Закрыв SpaceWar - у вас скорее всего закроется Unity. И нужно будет её повторно запускать. Эти проколы я не смог решил. Причем, после долгой работы, у меня даже зависал SpaceWar. И приходилось перезапускать Steam.
По началу, я не мог понять, почему у меня после получения RI.Hid отваливались контроллеры. Даже переставали идти вызовы UnityEngine.Input. Приходилось перезапускать и Steam и Unity.
Вызовы Steamworks для события Jump, то появлялись, то проходили мимо. Так я полез во второе решение Steamworks.NET. Но результат был только хуже. В итоге после целого дня ударов об стену, нашел следующую рекомендацию:
Launch your steam client with the following command line parameter: -forcecontrollerappid your_game's_AppID . This ensures that controllers are bound to the game window and nothing else, which could interfere with your debugging session. Example: D:\Programs\Steam\Steam.exe -forcecontrollerappid 480. In your code make sure that you activate an ActionSet before trying to receive input data from this set.
Запустив Steam с командой “-forcecontrollerappid 480” - ошибка RI.Hid по прежнему была, но теперь Steamworks не терял контроллеры.
Steamworks.NET
Более сложное решение, но пока что мне оно нравится больше. Возможно потому, что я в Facepunch.Steamworks не нашел как вибрировать контроллером. Но вероятно, я плохо искал.
Установить Steamworks.NET можно через unitypackage, Package Manager через ссылку git или распаковать вручную, скачав архив с github. Я пробовал 1 и 3 варианты.
После установки нужно добавить AppID в файл steam_appid.txt. Он будет лежать в корне проекта игры. Для работы с Steamworks, автор добавил скрипт SteamManager. В нем происходит инициализация, обновление и завершение.
Сначала вызовем SteamManager.Initialized. Затем "простимулируем" систему ввода SteamInput.Init();
Нужно собрать инструкции внутриигровых действий. В Facepunch.Steamworks этого не требовалось. Но так как у нас мало таких действий, вот пример того, как это можно собрать:
Это своего рода кеширование. Мы заранее соберем всю информацию обработчиков действий, контроллеров и прочее.
Нужна информация о контроллерах:
Когда будете экспериментировать, обращайте внимание на документацию ISteamInput. STEAM_INPUT_MAX_COUNT - максимальное количество контроллеров, которые могут использоваться одновременно в конфигураторе системы ввода Steam.
А теперь давай поймаем событие Jump. Просто для примера, без прохода по массиву, возьму нулевой элемент из контроллеров:
А если хотите повибрировать :)
Перед обработкой событий системы ввода, можно также сделать вызов SteamInput.RunFrame(). Он синхронизует состояние API с последними доступными элементами ввода контроллера. Это автоматически выполняет SteamManager с помощью SteamAPI.RunCallbacks(), но чтобы задержка была минимально возможной, вы можете вызвать функцию RunFrame() непосредственно перед чтением состояния контроллера.
Выводы
Зачем я это всё здесь написал, а ты возможно и прочитал… Время! Просто у меня это заняло больше времени, чем займет у тебя после прочитанного.
Если собираешься выходить в Steam, то лучше всего использовать Steam Input. Как минимум игрок будет ближе к твоей игре своими устройствами вибрации ;)
А что использовать, Facepunch.Steamworks или Steamworks.NET ? Ну, начни с Facepunch.Steamworks. Мы рассмотрели лишь одну сторону - систему ввода, а тебе ещё понадобится две другие - достижения и облачное хранение…
Следующее в моем плане изучение работы достижений и облачное хранение. И вот тогда точно, я окончательно приму решение - Facepunch.Steamworks или Steamworks.NET.
Спасибо за внимание.
ДНО (даю немного обучения)
[Отредактировано]
Спасибо вам за комментарии. После прочтения решил, что нужно сказать...
Не в коем случае я не настаиваю использовать steamworks ради Steam Input, тем более Steam Input вместо Input System Unity. Статья лишь демонстрирует, как завести устройства через Steam Input, ну и как воспользоваться частью Steam API.
Сам я недавно перешел на Input System в Unity и это отличная штука. Всем, кто начинает работать с Unity, начинайте с Input System. А те, кто работают давно, думаю и так этим пользуются.
Комментарий недоступен
Комментарий недоступен
Да, я ж не настаиваю использовать steamworks ради Steam Input, тем более Steam Input вместо Input System. Новая Input System в Unity отлично справляется со всем. Хоть я сам в основном сижу на старой системе ввода.
Статья лишь демонстрирует, как завести устройства через Steam Input.
Как здорово что в анрил энджин всё работает из коробки
Комментарий недоступен
Еще бы не забывали добавлять в меню ручной выбор отображения раскладки, как в Streets of Rage 4: Xbox, Playstation, Nintendo. Выбираешь, кнопки адекватно подписываются. Это важно и для поддержки основных геймпадов и сторонних с различной раскладкой (под Xbox или для ретро-игр под Nintendo)
Для меня, как для обывателя который не в курсе программирования, это тоже вопрос.
Мне не так много игр попадались , где есть выбор раскладки прям в меню. Например помнится подобное было в финальном сезоне Волкин Дэд, в Салт Н Санктуари, в какой-то из частей Триалс (которые про мотоциклы игра) и ещё в каких-то играх вроде встречалось.
Вот прям в меню зашёл и выбрал раскладку бокса или сони. Даже если у тебя условный Логитек Ф710 . Что очень удобно ибо тот же дуалшок 4 в стиме видит дуалшок и показывает раскладку Сони, а в игре (если не по проводу цеплять геймпад, по-крайней мере так слышал) пиктограммы бокса и ничего не поделать.
Для ДС Ремастеред вообще пришлось какую-то прогу качать с нексуса (впервые за всё время пользования компом там что-то качал, та и в целом редко ставлю какие-то моды сторонние) и через неё заменять значки на соньковские. Хотя игра может их показывать нативно, но у меня через блютус не показывает..
Или бывают мне, опять же..обывателю, непонятные моменты , когда вот СтимВорлд Диг 2 в стиме показывает значки бокса, а пиратка этой же игры сама, без стима или дс4вин определяет геймпад как дуалшок и показывает значки соньки =)
Не знаю насколько трудно реализовывать это меню выбора раскладки , поэтому не понимаю почему этого нет если не в почти всех играх, то хотя бы где-то в половине . Если , например, они итак выходили и на соньках и на боксах и на свитче, то есть всё равно пиктограммки уже есть в коробке с игрой.
Поскольку не понимаю ничего в создании игр, стараюсь не бесится по этому поводу и просто решил что значит всё там не так просто, иначе бы многие так и делали :)