Вы находитесь на странице: 1из 68

Game

Development

Unreal Engine

MIDDLE
Урок 5
Создание виджета
инвентаря

Материалы урока доступны по ссылке.

2
Инвентарь. Создание виджета инвентаря

Инвентарь.
Создание виджета инвентаря
Инвентарь — это элемент игрового интерфейса, ши-
роко используемый во множестве проектов, от детских
приключенческих игр до шутеров от первого лица и RPG.
В инвентаре персонажа могут храниться предметы,
необходимые для выполнения квестов, оружие и доспе-
хи, пища, зелья, драгоценности. При этом все собранные
объекты нередко рассортированы по категориям (рис. 1).

Рисунок 1
Давайте создадим собственный инвентарь на движ-
ке Unreal Engine 4. Для этого воспользуемся шаблонной
сценой Inventory System c видом сверху (Top Down). Ее
можно найти в дополнительных материалах. В данном
проекте уже реализована первичная структура и логика.

3
Урок 5

Наша задача — создать виджет инвентаря. По сути,


это небольшой графический элемент, в котором будут ото-
бражаться собранные предметы. Добавим в папку Widget
специальный блупринт: ПКМ => User Interface => Wid-
get Blueprint. Переименуем его в w_InventorySlot (рис. 2).

Рисунок 2
Откроем редактор данного блупринта и составим
следующую структуру. Добавим Size Box, внутрь кото-
рого поместим Canvas Panel, содержащий кнопку (But­
ton) (рис. 3).

Рисунок 3
Также зададим элементу Size Box значение Desired on
Screen, чтобы инвентарь масштабировался согласно со-
держимому (рис. 4).

4
Инвентарь. Создание виджета инвентаря

Рисунок 4
Зададим высоту и ширину этого элемента — 65х65
(рис. 5).

Рисунок 5

5
Урок 5

Также проверим, совпадают ли размеры Canvas Panel


и Size Box. Для этого значения выравнивания (Alignment)
должны быть выставлены в режим заполнения, как по-
казано на рисунке 6.

Рисунок 6
Далее займемся кнопкой. Данный элемент должен
полностью заполнять пространство Canvas Panel. Для
этого переведем его в режим заполнения (выпадающее
меню Anchors) и обнулим размеры по осям X и Y (рис. 7).

Рисунок 7

6
Инвентарь. Создание виджета инвентаря

Настроим внешний вид разных состояний кнопки. Во


вкладке Normal назначим изображение Inventory­Button
в слот Image. Дополнительно поменяем цвет кнопки на
серый в строке Tint (рис. 8).

Рисунок 8
Таким же образом настроим внешний вид остальных
состояний, поменяв цвет для значений Hovered и Pressed
(рис. 9).

Рисунок 9

7
Урок 5

Далее добавим в кнопку объект Image и назовем его


ItemIcon (рис. 10).

Рисунок 10
Зададим ему следующие настройки (рис. 11):
■■ Padding — 1;
■■ заполнение по горизонтали и вертикали;
■■ Visibility — Hidden.

Рисунок 11

8
Инвентарь. Создание виджета инвентаря

После добавления объекта Image, добавим в Canvas


Panel объект Text (рис. 12).

Рисунок 12
Настроим его так, как показано на рисунке 13. В ре-
зультате текст разместится в правом нижнем углу ячейки.

Рисунок 13
Дополнительно уменьшим кегль и добавим небольшую
тень, чтобы текст не терялся на светлом фоне (рис. 14).

9
Урок 5

Рисунок 14
В конце скроем текст так же, как и иконку (рис. 15).

Рисунок 15

Рисунок 16

10
Инвентарь. Создание виджета инвентаря

Далее переходим в Event Graph данного блупринта


и создаем несколько переменных: SlotIndex, InventoryRef,
ItemInfo и Amount (рис. 16).
Далее создаем Custom Event с названием UpdateSlot.
Подключим к нему функцию isSlotEmpty с помощью бло-
ка Branch (рис. 17).

Рисунок 17
Пропишем логику True/False. Данные ветки будут
проверять, заполнена ли ячейка или нет, и показывать,
либо скрывать иконки объектов сбора (рис. 18–19).

Рисунок 18

11
Урок 5

Рисунок 19
Установим саму текстуру. Для этого скрипт должен
обратиться к ноде ItemInfo и с помощью блока Break вы-
вести информацию в ноду Set Brush from Texture. Про-
блем с размерами быть не должно, так как размер икон-
ки совпадает с размерами кнопки (рис. 20).

Рисунок 20
В конце добавим еще одну ноду — Set Visibility. Дан-
ный параметр указывает на то, что при клике по слоту,

12
Инвентарь. Создание виджета инвентаря

кликается не картинка, а элемент иерархии SlotButton, то


есть кнопка (рис. 21).

Рисунок 21
Теперь создадим логическую связь заполненной ячей-
ки и выводимого текста. Выделим объект Text и нажмем
Bind — Create Binding (рис. 22).

Рисунок 22
Переименуем созданную функцию в Text Amount
Binding.
Подключим значение Amount с помощью ноды String
к блоку Append. В слот А пропишем знак умножения (*),
а саму ноду Amount подключим в слот В. Данный скрипт

13
Урок 5

будет просчитывать количество объектов в ячейке ин-


вентаря и конвертировать это значение в текст (рис. 23).

Рисунок 23
Таким же образом создадим связь для поведения тек-
ста (Behavior) (рис. 24).

Рисунок 24

Рисунок 25

14
Инвентарь. Создание виджета инвентаря

По умолчанию текст должен быть скрыт так же, как


и иконка собираемого объекта. Чтобы движок автомати-
чески просчитывал, в каких ситуациях выводить текст,
сформируем следующий скрипт (рис. 25).
Теперь сформируем визуальный виджет самого ин-
вентаря — w_Inventory (рис. 26).

Рисунок 26
Создадим следующую иерархию вложенных элемен-
тов: Canvas Panel => Vertical Box => Border => Horizontal
Box => Text (рис. 27).

Рисунок 27
Выставим нулевые отступы (Padding) для элемента
Horizontal Box (рис. 28).

15
Урок 5

Рисунок 28
Также настроим текст (рис. 29):
■■ выравнивание по левому краю;
■■ текст — Inventory;
■■ размер шрифта — 22.

Рисунок 29

16
Инвентарь. Создание виджета инвентаря

После этого добавим в Horizontal Box кнопку с текстом.


С ее помощью можно будет закрыть инвентарь (рис. 30).

Рисунок 30
Выставим следующие отступы для текста: слева и спра-
ва по 10, сверху и снизу — 0. В строке Text пропишем X
(рис. 31).

Рисунок 31
Переименуем кнопку на Close Button и зададим ей
отступ 10 по левой стороне. Также переключим размер

17
Урок 5

(Size) на заполнение (Fill) и выровняем кнопку по пра-


вому краю области. Дополнительно зададим ей цвет, на-
пример, красный. После этого окрасим разными оттен-
ками состояния Hovered и Pressed (рис. 32).

Рисунок 32

Рисунок 33

18
Инвентарь. Создание виджета инвентаря

Далее добавим в поле Border элемент Size Box. Имен-


но в нем будут храниться ячейки самого инвентаря
(рис. 33).
Зададим высоту данного элемента — 250 (рис. 34).

Рисунок 34
А также фоновый цвет — черный со значением ­Alpha =
0,6. В результате инвентарь получится полупрозрачным
(рис. 35).

Рисунок 35
Внутрь SizeBox добавим еще несколько элементов,
как показано на рисунке (рис. 36).

19
Урок 5

Рисунок 36
Выделим Uniform Grid Panel и переименуем ее в Slot
Panel. Отметим галочкой значение Is Variable, чтобы ячей-
ки могли менять свой внешний вид. Также зададим Slot
Padding = 5 (рис. 37).

Рисунок 37
После этого вернемся к SizeBox и зададим выравни-
вание по центру в строке Horizontal Alignment (рис. 38).
Этап визуализации завершен. Теперь необходимо
прописать логику поведения ячеек.

20
Инвентарь. Создание виджета инвентаря

Рисунок 38
Перейдем в Event Graph. Создадим функцию Gener­
ateSlotWidget (Сгенерировать виджет слота) и две пере-
менные: Inventory (Инвентарь) и SlotPerRow (Количество
строк со слотами) (рис. 39).

Рисунок 39
Выставим значение последней функции — 5. То есть,
в инвентаре не может появиться больше 5 строк с ячей-
ками (рис. 40).

Рисунок 40

21
Урок 5

Далее вернемся в функции GenerateSlotWidget. Пре-


жде всего подключим ноду Clear Children, которая долж-
на очищать Slot Panel.
После этого можно вновь заполнить инвентарь. Для
этого подключаем ноды Inventory => Target Slots в блок
ForEachLoop (рис. 41).

Рисунок 41
Далее возьмем функцию Create Widget с классом
W_InventorySlot и подключим его к ноде Add Child to Uni­
form Grid. В конце ветки подключим ноды Set Row и Set
Column, которые отвечают за количество строк и коло-
нок в инвентаре (рис. 42).
Создадим формулы, которые будут просчитывать
максимальное количество слотов, относительно которо-
го будет выстраиваться высота инвентаря. Вспомогатель-
ная нода Truncate позволяет избавиться от значений по-
сле запятой, то есть в ячейке будут отображаться только
целые числа (рис. 43).
Похожим образом просчитываем и количество ко-
лонок (рис. 44).

22
Инвентарь. Создание виджета инвентаря

Рисунок 42

Рисунок 43

Рисунок 44

23
Урок 5

Все столы инвентаря нужно записывать. Чтобы это


реализовать, создадим массив Slots Widgets, тип — w_In­
ventorySlots (рис. 45).

Рисунок 45
Подключим данный массив после ноды Create Wid­
get (рис. 46).

Рисунок 46

24
Инвентарь. Создание виджета инвентаря

А также после Clear Children со значением Clear


(рис. 47).

Рисунок 47
Далее создадим еще один UI-виджет w_MainWidget
(рис. 48).

Рисунок 48
Откроем редактор. Найдем виджет W_Inventory и раз-
местим его в том месте экрана, где должен отображаться
инвентарь (рис. 49).
Переименуем объект в InventoryWidget и пометим
галочкой Size to Content (рис. 50).

25
Урок 5

Рисунок 49

Рисунок 50
Далее перейдем в Event Graph данного блупринта
и создадим две переменные Inventory и SlotsPerRow со
значениями Instance Editable и Expose on Spawn (рис. 51).

26
Инвентарь. Создание виджета инвентаря

Рисунок 51
Пропишем логику для EventConstruct, где Inventory
Widget будет обращаться к нодам локальных перемен-
ных. В результате вся информация должна попасть в ноду
Generate Slot Widget (рис. 52).

Рисунок 52

Рисунок 53

27
Урок 5

Вернемся в bp_Inventory. Найдем ветку Event Begin­


Play и подключим к блоку Resize ноду Create Widget с клас-
сом W_MainWidget. В строку Inventory подключим Self.
Также создадим локальный SlotsPerRow (Promote to Vari­
able) со значениями Instance Editable и Expose on Spawn,
количество слотов — 4. Подключим его в соответствую-
щую строку (рис. 53).
Дополнительно создадим еще две локальных пере-
менных — Main Widget и Inventory Widget. Соединим их
с целевой нодой Inventory Widget и подключим данную
конструкцию в ноду Add to Viewport, которая и визуали-
зирует инвентарь на экране (рис. 54).

Рисунок 54
Чтобы объекты отображались в инвентаре, создадим
Custom Event — UpdateSlotAtIndex с входящим параме-
тром Index и подключим Inventory Widget с помощью
массива Slots Widget к ноде Update Slot (рис. 55).

Рисунок 55

28
Инвентарь. Создание виджета инвентаря

Затем вернемся к функции AddItem и добавим ноду


Update Slot at Index с индексом Local Found Index после
ноды Set Array Elem (рис. 56).

Рисунок 56
Скопируем эти блоки и добавим во все ветки после
ноды Set Array Elem.
После этого запускаем игру и начинаем собирать пред-
меты. Если все скрипты выстроены правильно, в инвен-
таре отобразятся бутылки с зельями (рис. 57).

Рисунок 57

29
Урок 5

Напоследок давайте рассмотрим несколько примеров


того, как реализованы инвентари в разных играх:
■■ Divinity: Original Sin (рис. 58);

Рисунок 58
■■ Dragon Age: Inquisition (рис. 59);

Рисунок 59

30
Инвентарь. Создание виджета инвентаря

■■ Prey (рис. 60);

Рисунок 60
■■ Freddi Fish (рис. 61).

Рисунок 61

31
Урок 5

■■ Fortnite (рис. 62).

Рисунок 62

32
Дополнительные материалы

Дополнительные
материалы
Любой проект, прежде всего, нужно структурировать.
Давайте для этого создадим новую папку Inventory­System
и добавим в нее еще 4 папки (рис. 1):
■■ Blueprint;
■■ DragAndDrop;
■■ Textures;
■■ Widget.

Рисунок 1
В папке c текстурами создадим еще одну папку Item­
Icons, в которую загрузим иконки предметов для сбо-
ра — карту, зелье и кольцо. Каждый из этих предметов
будет обладать уникальными свойствами и настройка-
ми (рис. 2).
Также, в корень папки Textures загрузим изображе-
ние InventoryButton (рис. 3).

33
Урок 5

Рисунок 2

Рисунок 3
Зайдем в редактор данной текстуры и зададим ей сле-
дующие настройки (рис. 4):
■■ Texture Group => UI, так как данный элемент является
частью пользовательского интерфейса;
■■ Compression => UserInterfase2D (RGBA), для 2D-изоб­
ра­жения.
Далее вернемся в папку с иконками. Выделим все объ-
екты, кликнем ПКМ и вызовем команду Asset Action =>
Bulk Edit via Property Matrix. Данная функция позволяет
одновременно редактировать несколько подобных объ-
ектов (рис. 5).

34
Дополнительные материалы

Рисунок 4

Рисунок 5
Зададим иконкам общую текстурную группу Texture
Group => UI, а также Compression Settings => UserInter­
fase2D (RGBA). Далее нажимаем Ctrl+Shift+S => Save All,
чтобы сохранить все изменения (рис. 6).

35
Урок 5

Рисунок 6
Далее структурируем все виды объектов. Для этого
в папке Blueprint создадим подпапку Structure и доба-
вим в нее специальный одноименный блупринт: ПКМ =>
Blueprints => Structure. Назовем его S_ItemInfo (рис. 7).

Рисунок 7
Откроем редактор данного блупринта и создадим
7 классов переменных (рис. 8):
1. Наименование — Name с типом Text.
2. Описание объекта — Description, также с типом Text.
3. Иконки — Icon, тип Texture2D.

36
Дополнительные материалы

4. Переменная, отвечающая за возможность исполь­


зования объекта, — canBeUsed, тип Boolean.
5. Описание свойств объекта — UseText, тип Text.
6. Переменная для суммирования объектов в одной
ячейке — canBeStacked, тип Boolean.
7. Категория объекта, которая будет определять, к какой
группе относится тот или иной предмет — Category.

Рисунок 8
Чтобы настроить тип последнего класса переменных,
необходимо создать дополнительный блупринт Enumer­
ation. Он будет содержать в себе перечисление всех до-
ступных видов объектов. Создадим в папке Blueprints
дополнительную папку Enums и добавим в нее блупринт

37
Урок 5

с названием e_ItemCategories (меню Blueprints => Enu­


meration) (рис. 9).

Рисунок 9
Откроем редактор и добавим 4 типа объектов (рис. 10):

Рисунок 10
1. Consumable — потребляемые предметы (зелья, пища,
напитки и т.д.).
2. Equipment — любые предметы, которые можно одеть
на персонажа (доспехи, кольца и т.д).

38
Дополнительные материалы

3. Quest — любые уникальные предметы, необходимые


для выполнения заданий.
4. Readables — предметы, содержащие дополнительную
информацию об игровом мире или задания (книги,
свитки и т.д.).
После этого вернемся к блупринту S_ItemInfo и на-
значим новый тип E_ItemInfo переменной Category.

Рисунок 11
Дополнительно выставим настройки по умолчанию
(Default Values) для всех новых объектов, как показано

39
Урок 5

на рисунке 11. Сохраним настройки и выйдем из редак-


тора. После этого в папке Blueprint создадим еще одну
папку ItemClasses для разных классов объектов. Добавим
в нее блупринт с классом Actor и назовем его bp_Master­
Item (рис. 12).

Рисунок 12
Откроем редактор данного блупринта и добавим
в него переменную ItemInfo с типом S_ItemInfo, который
был создан ранее (рис. 13).

Рисунок 13

40
Дополнительные материалы

Также создадим в данном блупринте Custom event


с названием EventOnUse (рис. 14).

Рисунок 14
Далее вернемся в папку ItemClasses. Выделим bp_Mas­
terItem и создадим для него дочерний класс блупринта:
ПКМ => Create Child Blueprint Class. Назовем его Item­
HealthPotion (рис. 15).

Рисунок 15
Откроем редактор и зададим настройки по умолча-
нию для данного объекта, как на рисунке 16. Введем имя
предмета — HealthPotion (Зелье здоровья), а также краткое
описание его функций — Use potion for refill your health
(Используй зелье, чтобы восстановить здоровье). Также
подключим иконку объекта в пункте Icon. Далее идут
41
Урок 5

настройки самих свойств предмета. Отметим галочка-


ми пункты canBeUsed и canBeStacked, добавим подсказ-
ку Drink Me, а также зададим категорию — Consumable,
то есть применяемый объект.

Рисунок 16
Аналогичным образом поступим с двумя другими
объектами — картой и кольцом. Создадим еще два до-
черних класса блупринтов для bp_MasterItem: ItemMap
и ItemRing (рис. 17).

Рисунок 17
Настроим данные блупринты по аналогии с зельем.

42
Дополнительные материалы

Рассмотрим отличия. В одной ячейке может хранить-


ся только одна карта, поэтому необходимо снять галоч-
ку с пункта canBeStacked в блупринте Map. Также карта
попадает в другую категорию предметов — Readables,
объекты, которые содержат дополнительную информа-
цию (рис. 18).

Рисунок 18

Рисунок 19

43
Урок 5

Теперь создадим структуру для ячеек инвентаря —


S_InventorySlot (рис. 20).
Кольцо — это уникальный квестовый предмет, поэто-
му необходимо снять галочки как в пункте canBeStacked,
так и в пункте canBeUsed. Категория предмета — Quest
(рис. 19).

Рисунок 20
Создадим две переменные: Item Class типа Bp_Master­
Item c классом Reference, и Amount для подсчета количе-
ства ячеек, тип Integer (рис. 21).

Рисунок 21
Сохраняем изменения.
Далее вернемся в папку блупринтов и создадим но-
вый Blueprint типа Actor для самого инвентаря. Переи-
менуем его в bp_Inventory (рис. 22).

44
Дополнительные материалы

Рисунок 22
В редакторе данного блупринта создадим перемен-
ные AmountOfSlots (Количество слотов) и MaxStackSize
(Максимальный размер стека) типа Integer (рис. 23).

Рисунок 23

Рисунок 24
Далее создадим переменную для референса персона-
жа с типом Top Down Character. Дополнительно отметим
галочками опции Instance Editable (Редактируемый объ-

45
Урок 5

ект) и Expose on Spawn (Выставить в точке спауна). Эти


же галочки выставим и для переменной AmountOfSlots
(рис. 24).
После этого создадим массив слотов инвентаря —
Array. Назовем его Slots, тип переменной — S_Invento­
rySlot (рис. 25).

Рисунок 25
Прежде всего зададим адаптивность инвентаря в за-
вистимости от количества слотов, заложеного в проект.
Для этого соединим ноду Event BeginPlay, массив Slots
и Amount Of Slots с помощью блока Resize (рис. 26).

Рисунок 26
Далее создадим новую функцию isSlotEmpty?, которая
будет проверять заполненность ячеек (рис. 27).

46
Дополнительные материалы

Рисунок 27
Зададим ей следующие настройки: добавим два па-
раметра входящих и исходящих данных в блоках Inputs
и Outputs. Также отметим галочкой параметр Pure, что-
бы движок не менял состояние классов (рис. 28).

Рисунок 28
Сформируем проверочный скрипт, работающий на
базе логики True/False. Для этого воспользуемся нода-
ми Break и Is Valid Class. Соединим из с массивом Slots
так, как показано на рисунке 29. В результате, если вну-

47
Урок 5

три слота будет находится предмет, сработает последо-


вательность Item Class is Valid, и программа поймет, что
ячейка занята.

Рисунок 29
Следующая функция, которую необходимо создать, —
GetItemInfoAtIndex. Также добавим ей несколько пара-
метров: один входящий и три исходящих. Дополнитель-
но отметим галочкой значение Pure, как и в предыдущей
функции (рис. 30).

Рисунок 30
Первая половина скрипта, по сути, дублирует пре-
дыдущий. Далее необходимо включить блок Branch, от-
48
Дополнительные материалы

вечающий за условие логики True/False. Если сработает


значение True, блок Break должен обратиться к ноде Get
Class Default, в противном случае скрипт напрямую об-
ратится к блоку Return Node с активированной строкой
Empty Slot (рис. 31).

Рисунок 31
Создадим еще одну функцию SearchEmptySlot — по-
иск пустого слота. Создадим для нее два исходящих па-
раметра: Success и Index (рис. 32).

Рисунок 32
Подключим к ней массив Slots через ноду ForEachLoop­
WithBreak, чтобы цикл прерывался каждый раз, когда
будет найден пустой слот. После этого подключим ноду
Branch (рис. 33).

49
Урок 5

Рисунок 33
Далее воспользуемся локальными переменными, ко-
торые будут применяться исключительно к этой функ-
ции. Создадим две переменные: local_Bool и localIndex
(рис. 34).

Рисунок 34
Подключим их в скрипт, в ветку True co значением
Set. Отметим галочкой Local Bool, а индекс подключим
в соответствующую строку блока Loop, как показано на
рисунке 35.

Рисунок 35

50
Дополнительные материалы

После этого замкнем скрипт в строке Break блока


Loop и подключим ноды Local Bool и Local Index в соот-
ветствующие строки Return Node (рис. 36).

Рисунок 36
Теперь создадим функцию Search free stack — поиск
свободного стека в инвентаре. Добавим один входящий
параметр ItemClass и два исходящих — Success и Index
(рис. 37).

Рисунок 37
Повторяем стартовую логику скрипта. После это до-
бавим блок Equal, который подключим в строки Item

51
Урок 5

Class блоков Break и стартового Search Free Stack. Также


проверим, является ли значение Max Stack Size большим,
чем значение Amound. Далее копируем Branch и соеди-
няем его с нодой Equal с помощью блока And (рис. 38).

Рисунок 38
Осталось создать две локальные переменные local_
Bool и localIndex, как и в прошлой функции (рис. 39).

Рисунок 39
Следующая функция — AddItem (Добавление предме-
тов). Входящие параметры — ItemClass и Amount, исхо-
дящий — Success. Данная функция немного отличается
от предыдущих. Именно она должна складывать одина-

52
Дополнительные материалы

ковые предметы сбора в одну и ту же ячейку. Первичная


конструкция показана на рисунке 40.

Рисунок 40
Если предмет уникален, и ячейка может содержать
только один подобный объект, должна срабатывать ло-
гика False. Скрипт должен обратиться к функции Search
Empty Slot, проверить Local Found Index и перейти к ноде
Set Array Elem, где Target Array — это Slots, а Item — Lo­
cal Item Class (рис. 41).

Рисунок 41
Чтобы предметы добавлялись в ячейку поштучно,
подключим к ноде Set Array блок Add Item с проверкой,
является ли числовое значение Local Amount >1. То есть,

53
Урок 5

если перед игроком будет лежать 5 идентичных предме-


тов, ему придется поднять их 5 раз. В конце закрываем
скрипт Return Node, активировав строку Success. При
значении False будет напрямую срабатывать блок Return
Node (рис. 42).

Рисунок 42
Напоследок добавим такой же блок в значение False
функции Search Empty Sloth (рис. 43).

Рисунок 43

54
Дополнительные материалы

Теперь сформируем логику значения True корневой


функции Add Item. Прежде всего добавим ноды Search
Free Stack => Branch. Для значения False сработает функ-
ция Search Empty Slot (рис. 44).

Рисунок 44
Если пустая ячейка найдена, сработает значение True,
которое запустит следующий скрипт (рис. 45).

Рисунок 45
В результате в ячейку будет добавлен предмет, если он
не превышает допустимое количество объектов в ячей-
ке, и цикл завершится (рис. 46).
Для значения False срабатывает следующая ветка
(рис. 47).

55
Урок 5

Рисунок 46

Рисунок 47
Если свободный стек все же найден, получаем Local
Found Index. Суммируем его с Local Amount и проверя-
ем, чтобы данное число не оказалось больше значения
MaxStackSize (рис. 48).
Далее прописываем логику True/False. Отрицатель-
ное значение должно учитывать суммированную пере-
менную Local Found Index и Local Amount (рис. 49).

56
Дополнительные материалы

Рисунок 48

Рисунок 49
Ветка True показана на рисунке 50.

Рисунок 50

57
Урок 5

Создадим еще одну функцию — GetAmountAtIndex.


Благодаря ей мы получим сумму предметов в слотах. До-
бавим входящий параметр Index и исходящий Amount.
Также отметим галочкой параметр Pure (рис. 51).

Рисунок 51
Сформируем следующий скрипт (рис. 52).

Рисунок 52
Далее выделим переменную MaxStackSize и пропи-
шем для нее значение максимального количества пред-

58
Дополнительные материалы

метов, которые будут помещаться в ячейке, к примеру,


99 (рис. 53).

Рисунок 53
Таким же образом пропишем максимальное количе-
ство ячеек в инвентаре — 20 (рис. 54).

Рисунок 54
После этого подкорректируем функцию AddItem.

59
Урок 5

Добавим ей еще одно Output-значение — Rest (Оста-


ток) (рис. 55).

Рисунок 55
Теперь подключим ноду Local Amount в строку Rest
в следующих ветках. Данный параметр позволит реали-
зовать логику, в которой все равно будет отображено ко-
личество предметов, даже если нельзя добавить новые
объекты в инвентарь (рис. 56–59).

Рисунок 56

Рисунок 57

60
Дополнительные материалы

Рисунок 58

Рисунок 59
Следующий этап — создать шаблон самих предметов
сбора и прописать логику их добавления в инвентарь.
Прежде, чем создать сам объект, перейдем в блупринт
персонажа. Подключим к ноде Event BeginPlay блок Spawn­
Actor frow Class с классом bp_Inventory. Данное действие
отвечает за вызов инвентаря. Замкнем данный блок на
самого персонажа (Self) и выставим настройки Collision
Handing Override на Always Spawn, Ignore ­Collisions. В кон-

61
Урок 5

це добавим новую переменную (ПКМ по строке Return


Value => Promote to Variable) и назовем ее InventoryRef
(рис. 60).

Рисунок 60
Далее создаем новый блупринт для объекта сбора
с классом Actor. Называем его bp_PickUpActor (рис. 61).

Рисунок 61
Заходим в редактор, создаем объект Sphere Collision
и подключим к нему дочерний объект Static Mesh, кото-
рый переименуем на Potion Bottle (рис. 62).

62
Дополнительные материалы

Рисунок 62
Подключим на данный мэш модель бутылки с зельем.
Ее можно найти на любом сайте с 3D-моделями, либо
воспользоваться сеткой, заранее загруженной в шаблон
(рис. 63).

Рисунок 63
Далее выделим объект Sphere Collision и добавим ему
ноду On Component Begin Overlap (рис. 64).

Рисунок 64
Подключим к ней ноду самого персонажа (Cast to
TopDown Character). Данная нода должна обращаться

63
Урок 5

к инвентарю и проверять его на валидность. После это-


го объект должен добавиться в инвентарь, то есть сра-
ботает нода AddItem с двумя локальными переменными
ItemClass и Amount (рис. 65).

Рисунок 65
Дополнительно в обеих локальных переменных от-
мечаем галочками пункты Instance Editable и Expose On
Spawn (рис. 66).

Рисунок 66

64
Дополнительные материалы

Далее нужно проверить остаток. Если он больше 0 (не


все предметы в сцены были собраны), сработает ветка
True с нодой Set Amount. В противном случае, если пред-
метов больше нет, скрипт обратиться к ноде DestroyAc­
tor, и предмет сбора исчезнет из сцены (рис. 67).

Рисунок 67
Сохраним изменения. Теперь можно проверить, сра-
батывает ли скрипт. Для этого нужно разместить не-
сколько предметов сбора в сцене, например, две бутыл-
ки и свиток (рис. 68).

Рисунок 68

65
Урок 5

Зададим им разные значения, чтобы проверить логи-


ку добавления большого количества объектов в инвен-
тарь. Выставим значение Amount на 50 для первого зелья
и 150 — для второго. Так же поступим с картой, задав ей
значение 2. Также не забываем задать соответствующие
классы (Item Class) каждому предмету сбора (рис. 69).

Рисунок 69
Базовая сцена готова, теперь можно приступать к ви-
зуализации самого инвентаря.

66
Дополнительные материалы

67
Урок 5
Создание виджета инвентаря

© Компьютерная Академия «Шаг»


www.itstep.org

Все права на охраняемые авторским правом фото-, аудио- и видеопро-


изведения, фрагменты которых использованы в материале, принадле-
жат их законным владельцам. Фрагменты произведений используются в
иллюстративных целях в объёме, оправданном поставленной задачей, в
рамках учебного процесса и в учебных целях, в соответствии со ст. 1274
ч. 4 ГК РФ и ст. 21 и 23 Закона Украины «Про авторське право і суміжні
права». Объём и способ цитируемых произведений соответствует
принятым нормам, не наносит ущерба нормальному использованию
объектов авторского права и не ущемляет законные интересы автора
и правообладателей. Цитируемые фрагменты произведений на момент
использования не могут быть заменены альтернативными, не охраня-
емыми авторским правом аналогами, и как таковые соответствуют
критериям добросовестного использования и честного использования.
Все права защищены. Полное или частичное копирование материалов
запрещено. Согласование использования произведений или их фраг-
ментов производится с авторами и правообладателями. Согласованное
использование материалов возможно только при указании источника.
Ответственность за несанкционированное копирование и коммерческое
использование материалов определяется действующим законодатель-
ством Украины.

Вам также может понравиться