09/04/2019

Настройка Game User Settings & Input Settings

Всем привет! В этом уроке я расскажу как создавать полноценный модуль для настроек в вашей игре или приложении. А также покажу как можно переназначать клавиши для игровых действий во время игры. 

Настройки игры

Настройка виджетов

Перво-наперво создадим удобные инструменты для тестирования функционала, а именно — виджеты, которыми мы будем регулировать настройки графики.

Используются элементы ComboBox, CheckBox.

Каждый из элементов рекомендую назвать узнаваемым именем, чтобы не запутаться в дальнейшем.

Не забудьте добавить виджет на экран при старте игры, например, повесив вызов на Event BeginPlay в Level Blueprint'е.

Создание файла настроек (на случай его отсутствия)

На старте программы следует загрузить существующие настройки игры в память компьютера. Если их по какой-то причине не будет на диске, создастся новый ini файл со стандартными параметрами, а все дальнейшие изменения будут записываться в него.

Заполнение виджетов значениями текущих настроек

Создание списка поддерживаемых разрешений.

С функцией GetSupportedFullscreenResolution получаем массив поддерживаемых разрешений монитора. Массив будет типа IntPoint — это 2 INT-числа, соответственно, разрешение в пикселях по X и У. Формируем строку формата 1920х1080, чтобы положить её в выпадающий список.

Заполняем ComboBox, отвечающий за список разрешений экрана

Устанавливаем отображение текущих настроек на виджетах.

Выставляем отображение текущего разрешения в ComboBox
Выставляем статус полноэкранного режима
Выставляем статус вертикальной синхронизации
Выставляем отображение текущей настройки теней
Настройки сглаживания
Настройки качества постпроцессинга

В итоге должна получиться вот такая многоэтажка из блупринтов:

Когда вы её сделаете, при старте игры в виджетах будут находиться текущие настройки графики.

Изменение настроек

В каждом виджете есть свои события, например, нажатие на кнопку, изменение выбранной опции в комбо-боксе, изменение статуса в чек-боксе и так далее. На эти события мы повесим логику, которая записывает новые значения в GameUserSettings, но не применяет их. Применим позже.

Задать разрешение экрана
Фуллскрин и вертикальная синхронизация
Тени и сглаживание
И постпроцессинг

В итоге для каждого события мы меняем те или иные параметры в настройках, выставляя нужное качество графики.

Для многих параметров требуется входное целочисленное значение (Int) (0, 1, 2, 3 или 4).

Применить настройки

А теперь, чтобы применить настройки графики надо повесить этот код на нажатие кнопки Apply.

Теперь после изменений настроек можно нажать Apply и они применятся к игре.

Переназначение клавиш

Создадим виджет-строку

Она будет демонстрировать определённое действие и клавишу, на которую она завязана. И добавим в неё кнопку для переназначения клавиши ввода.

Обратите внимание на аннотации в скриншоте. Размер виджета Desired, элемента CanvasPanel'а в иерархии нет.

Теперь в основном виджете создадим контейнер

В нём будет находиться список из тех виджетов, класс которых мы только что создали. Просто VerticalBox.

На EventConstruct повесим заполнение этого контейнера виджетами-элементами списка:

GetInputSettingsGetActionNames, далее в цикле 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

Recent Posts

Построение шейдера иридисценции в UE4

16/04/2019
Джеймс Эмори подробно разбирает процесс создания на UE4 шейдера иридисценции.

Создание реалистичного ремонта авто в VR-симуляторе

15/04/2019
Опытный игровой художник и увлеченный автомеханик-любитель направил свои уникальные знания и умения на создание VR–игры, посвященной починке автомобилей.

Нарратив в игре: изображение, темп, план

11/04/2019
Продолжаем раскрывать тему нарративных механик. Поговорим об изображениях, сменах плана, темпах и даже интерфейсе.