Настройка Game User Settings & Input Settings
Всем привет! В этом уроке я расскажу как создавать полноценный модуль для настроек в вашей игре или приложении. А также покажу как можно переназначать клавиши для игровых действий во время игры.
Настройки игры
Настройка виджетов
Перво-наперво создадим удобные инструменты для тестирования функционала, а именно — виджеты, которыми мы будем регулировать настройки графики.
Используются элементы ComboBox, CheckBox.
Каждый из элементов рекомендую назвать узнаваемым именем, чтобы не запутаться в дальнейшем.
Не забудьте добавить виджет на экран при старте игры, например, повесив вызов на Event BeginPlay в Level Blueprint'е.
Создание файла настроек (на случай его отсутствия)
На старте программы следует загрузить существующие настройки игры в память компьютера. Если их по какой-то причине не будет на диске, создастся новый ini файл со стандартными параметрами, а все дальнейшие изменения будут записываться в него.
Заполнение виджетов значениями текущих настроек
Создание списка поддерживаемых разрешений.
С функцией GetSupportedFullscreenResolution получаем массив поддерживаемых разрешений монитора. Массив будет типа IntPoint — это 2 INT-числа, соответственно, разрешение в пикселях по X и У. Формируем строку формата 1920х1080, чтобы положить её в выпадающий список.
Устанавливаем отображение текущих настроек на виджетах.
В итоге должна получиться вот такая многоэтажка из блупринтов:
Когда вы её сделаете, при старте игры в виджетах будут находиться текущие настройки графики.
Изменение настроек
В каждом виджете есть свои события, например, нажатие на кнопку, изменение выбранной опции в комбо-боксе, изменение статуса в чек-боксе и так далее. На эти события мы повесим логику, которая записывает новые значения в GameUserSettings, но не применяет их. Применим позже.
В итоге для каждого события мы меняем те или иные параметры в настройках, выставляя нужное качество графики.
Для многих параметров требуется входное целочисленное значение (Int) (0, 1, 2, 3 или 4).
Применить настройки
А теперь, чтобы применить настройки графики надо повесить этот код на нажатие кнопки Apply.
Теперь после изменений настроек можно нажать Apply и они применятся к игре.
Переназначение клавиш
Создадим виджет-строку
Она будет демонстрировать определённое действие и клавишу, на которую она завязана. И добавим в неё кнопку для переназначения клавиши ввода.
Обратите внимание на аннотации в скриншоте. Размер виджета Desired, элемента CanvasPanel'а в иерархии нет.
Теперь в основном виджете создадим контейнер
В нём будет находиться список из тех виджетов, класс которых мы только что создали. Просто VerticalBox.
На EventConstruct повесим заполнение этого контейнера виджетами-элементами списка:
GetInputSettings→ GetActionNames, далее в цикле GetActionMappingByName, чтобы получить массив кнопок для текущего Action'а. Для каждого Action'а необходимо создать свой виджет и передать в него на хранение сам ActionMapping, на основе котрого (функция SetContent) виджет заполнит свои элементы нужными названиями дейсвия и кнопки. Ну и в конце добавляем созданный виджет в VerticalBox.
Функция SetContent в виджете-строке
Этот шаг, на самом деле, стоит перед предыдущим, т.е. функцию надо создать, чтобы её вызвать :)) (см. скриншот сверху)
Назначаем переопределение (Override) для уже существующей по умолчанию функции OnKeyDown
Нажмите на кнопку Override и выберите нужную функцию из списка доступных для переопределения.
В этой функции будет находиться самое мясо.
В первую очередь, берём из входного параметра нажатую клавишу (Key) с помощью функции GetKey и кладём её в переменную. Она нам понадобится чуть позднее.
Далее с помощью цикла в цикле определяем не назначена ли эта клавиша уже на какой-либо из Action Input'ов:
В этом куске логики мы берём все имена существующих в проекте Action'ов, далее в цикле перебираем их и для каждого из имён получаем массив клавиш, которые его могут вызывать. Проходя по этому массиву, сравниваем — равна ли клавиша той, которую нажал пользователь. Если пользователь нажал клавишу, на которую уже назначено действие, ничего не произойдёт, если же нажал на новую — логика пойдёт дальше. За это условие отвечает локальная булева переменная CannotUseThis, которая приобретает значение True только при совпадении.
И аналогичный кусок логики сразу следом, только уже предназначенный для перебора Axis-mapping'а:
Само условие того, будет ли переназначена клавиша или нет:
CanInput становится True после нажатия на кнопку в виджете (об этом будет позднее).
CannotUseThis становится True только если ранее в одном из циклов мы наткнулись на совпадение.
И само переназначение клавиш
Функции "изменить клавишу" в блупринтах нет, но есть функции удаления и добавления Action Mapping'а. Воспользуемся этим. Удалим текущий ActionMapping и изменим клавишу в нашей сохранённой переменной KeyMapp, чтобы позже её добавить как новый Mapping. Тут используется нода SetMembersIn… для того, чтобы изменить только конкретный(е) параметр(ы) в структуре. Ну, соответственно для мэппинга нам надо заменить только клавишу.
Следом обновляем информацию в виджете (SetContent), разрешаем ввод и назначаем новый ActionMapping.
Вишенка на торте
Сама кнопка, которая позволяет переназначить клавишу. На её нажатие надо повесить вот этот код:
Мы разрешаем ввод и переключаем фокус на виджет, в котором находится кнопка. Это необходимо сделать, потому что при клике на кнопке фокус перемещается конкретно на неё. И если нажать "пробел", он не будет воспринят как вводимая клавиша, а просто будет нажимать кнопку виджета раз за разом. Можете проверить сами, в видео я наглядно показал этот момент.
Настройки готовы! Ну, почти
Я не рассмотрел ряд настроек графики и надеюсь, что вы сами сможете их сделать по тому же принципу, что описан в первой части статьи.
Что касается инпутов — тут я не рассмотрел AxisMapping и надеюсь, что вы сможете решить эту задачу и для них, также наподобие второй части статьи.
Текст и видео: Даниил Лихоманов
UNREALSKILLS | Онлайн-курсы Unreal Engine 4