Как подружить 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, Unity и контроллеры

Создадим файл вручную. Внутри папки Steam создаем папку "controller_config" (например, C:/Program Files (x86)/Steam/controller_config) и там создаем файл game_actions_480.vdf

Где 480 - идентификатор приложения (AppID). В данном случае 480 - идентификатор игры SpaceWar (приложение-образец с API Steamworks)

Если у вас уже есть страница игры, то вместо 480 используйте свой AppID.

Я специально убрал всё лишнее, оставив лишь одно действие.

"In Game Actions" { "actions" { "GameControls" { "title" "#Set_GameControls" "Button" { "Jump" "#Action_Jump" } } } "localization" { "english" { "Set_GameControls" "Game Controls" "Action_Jump" "Jump" } "russian" { "Set_GameControls" "Общее управление" "Action_Jump" "Прыжок" } } }

GameControls - название группы действий, которое мы будем обрабатывать из кода. # Set_GameControls - ссылка для локализации настроек контроллера игрока.

Как подружить Steam, Unity и контроллеры

Jump - название действия, которое мы будем обрабатывать из кода. Соответственно # Action_Jump ссылается на значение, которое будет видеть игрок, изменяя событие на другую кнопку.

Как подружить Steam, Unity и контроллеры

Чтобы попробовать и понять как это работает, нам этого хватит. Более подробно о IGA

Facepunch.Steamworks

Начнем с более “дружелюбного” решения от Facepunch Studios (Rust и Garry's Mod). Установка простая: скачать и распаковать в директорию проекта.

Вызовы инициализации, обновления и завершения:

Steamworks.SteamClient.Init(480);

Steamworks.SteamClient.RunCallbacks();

Steamworks.SteamClient.Shutdown();

public class Test : MonoBehaviour { void Start() { try { Steamworks.SteamClient.Init(480); } catch (System.Exception e) { Debug.Log(e.Message); } } private void OnApplicationQuit() { Steamworks.SteamClient.Shutdown(); } void Update() { Steamworks.SteamClient.RunCallbacks(); } }

Запустив проект в Unity, после инициализации Facepunch.Steamworks подтянет файл с внутриигровыми действиями (IGA) game_actions_480.vdf. Запустится в Steam SpaceWar. И если у вас подключен контроллер, то вы сможете назначить действие Jump на одну из кнопок.

Как подружить Steam, Unity и контроллеры

А теперь давай поймаем событие Jump.

foreach (Steamworks.Controller controller in Steamworks.SteamInput.Controllers) { if (controller.GetDigitalState("Jump").Pressed) { Debug.Log("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 этого не требовалось. Но так как у нас мало таких действий, вот пример того, как это можно собрать:

InputActionSetHandle_t actionSet = SteamInput.GetActionSetHandle(“GameControls”); InputDigitalActionHandle_t digitalAction = SteamInput.GetDigitalActionHandle(“Jump”);

Это своего рода кеширование. Мы заранее соберем всю информацию обработчиков действий, контроллеров и прочее.

Нужна информация о контроллерах:

InputHandle_t[] controllers = new InputHandle_t[Constants.STEAM_INPUT_MAX_COUNT]; SteamInput.GetConnectedControllers(controllers);

Когда будете экспериментировать, обращайте внимание на документацию ISteamInput. STEAM_INPUT_MAX_COUNT - максимальное количество контроллеров, которые могут использоваться одновременно в конфигураторе системы ввода Steam.

А теперь давай поймаем событие Jump. Просто для примера, без прохода по массиву, возьму нулевой элемент из контроллеров:

InputDigitalActionData_t jump = SteamInput.GetDigitalActionData(controllers[0], digitalAction); if (jump.bActive > 0 && jump.bState > 0) { Debug.Log("Jump"); }

А если хотите повибрировать :)

SteamInput.TriggerVibration(controllers[0], 10000, 10000);

Перед обработкой событий системы ввода, можно также сделать вызов SteamInput.RunFrame(). Он синхронизует состояние API с последними доступными элементами ввода контроллера. Это автоматически выполняет SteamManager с помощью SteamAPI.RunCallbacks(), но чтобы задержка была минимально возможной, вы можете вызвать функцию RunFrame() непосредственно перед чтением состояния контроллера.

Ваша игра на Unity, что вы используете или собираетесь использовать для работы со Steam?
Facepunch.Steamworks
Steamworks.NET

Выводы

Зачем я это всё здесь написал, а ты возможно и прочитал… Время! Просто у меня это заняло больше времени, чем займет у тебя после прочитанного.

Если собираешься выходить в Steam, то лучше всего использовать Steam Input. Как минимум игрок будет ближе к твоей игре своими устройствами вибрации ;)

А что использовать, Facepunch.Steamworks или Steamworks.NET ? Ну, начни с Facepunch.Steamworks. Мы рассмотрели лишь одну сторону - систему ввода, а тебе ещё понадобится две другие - достижения и облачное хранение…

Следующее в моем плане изучение работы достижений и облачное хранение. И вот тогда точно, я окончательно приму решение - Facepunch.Steamworks или Steamworks.NET.

Подписывайся, читай твиттер, смотри youtube. Правда там пока не слишком насыщено, времени всё не хватает…

Как подружить Steam, Unity и контроллеры

Спасибо за внимание.

ДНО (даю немного обучения)

[Отредактировано]

Спасибо вам за комментарии. После прочтения решил, что нужно сказать...

Не в коем случае я не настаиваю использовать steamworks ради Steam Input, тем более Steam Input вместо Input System Unity. Статья лишь демонстрирует, как завести устройства через Steam Input, ну и как воспользоваться частью Steam API.

Сам я недавно перешел на Input System в Unity и это отличная штука. Всем, кто начинает работать с Unity, начинайте с Input System. А те, кто работают давно, думаю и так этим пользуются.

4747
16 комментариев

Комментарий недоступен

6
Ответить

Комментарий недоступен

3
Ответить

Да, я ж не настаиваю использовать steamworks ради Steam Input, тем более Steam Input вместо Input System. Новая Input System в Unity отлично справляется со всем. Хоть я сам в основном сижу на старой системе ввода.
Статья лишь демонстрирует, как завести устройства через Steam Input.

2
Ответить

Как здорово что в анрил энджин всё работает из коробки

5
Ответить

Комментарий недоступен

1
Ответить

Еще бы не забывали добавлять в меню ручной выбор отображения раскладки, как в Streets of Rage 4: Xbox, Playstation, Nintendo. Выбираешь, кнопки адекватно подписываются. Это важно и для поддержки основных геймпадов и сторонних с различной раскладкой (под Xbox или для ретро-игр под Nintendo)

2
Ответить

Для меня, как для обывателя который не в курсе программирования, это тоже вопрос.

Мне не так много игр попадались , где есть выбор раскладки прям в меню. Например помнится подобное было в финальном сезоне Волкин Дэд, в Салт Н Санктуари, в какой-то из частей Триалс (которые про мотоциклы игра) и ещё в каких-то играх вроде встречалось.
Вот прям в меню зашёл и выбрал раскладку бокса или сони. Даже если у тебя условный Логитек Ф710 . Что очень удобно ибо тот же дуалшок 4 в стиме видит дуалшок и показывает раскладку Сони, а в игре (если не по проводу цеплять геймпад, по-крайней мере так слышал) пиктограммы бокса и ничего не поделать.

Для ДС Ремастеред вообще пришлось какую-то прогу качать с нексуса (впервые за всё время пользования компом там что-то качал, та и в целом редко ставлю какие-то моды сторонние) и через неё заменять значки на соньковские. Хотя игра может их показывать нативно, но у меня через блютус не показывает..

Или бывают мне, опять же..обывателю, непонятные моменты , когда вот СтимВорлд Диг 2 в стиме показывает значки бокса, а пиратка этой же игры сама, без стима или дс4вин определяет геймпад как дуалшок и показывает значки соньки =)

Не знаю насколько трудно реализовывать это меню выбора раскладки , поэтому не понимаю почему этого нет если не в почти всех играх, то хотя бы где-то в половине . Если , например, они итак выходили и на соньках и на боксах и на свитче, то есть всё равно пиктограммки уже есть в коробке с игрой.
Поскольку не понимаю ничего в создании игр, стараюсь не бесится по этому поводу и просто решил что значит всё там не так просто, иначе бы многие так и делали :)

2
Ответить