background top icon
background center wave icon
background filled rhombus icon
background two lines icon
background stroke rhombus icon

Скачать "Build Procedural UI with Callbacks and Manipulators"

input logo icon
Теги видео
|

Теги видео

unity tutorial
unity arcade game
unity game tutorial
unity
game development
game dev
game development unity
programming
c#
software development
learn to code
learn programming
unity tutorials
unity devlog
indiedev
gamedev
unity3d
unity ui toolkit
unity ui toolkit inventory drag drop
unity ui toolkit drag drop
unity inventory system
Субтитры
|

Субтитры

subtitles menu arrow
  • enАнглийский
Скачать
00:00:00
Одно из наиболее востребованных видео на этом
00:00:02
канале было о создании
00:00:04
системы инвентаря, поэтому сегодня мы собираемся
00:00:07
создать процедурное представление для этой
00:00:09
системы инвентаря, которое позволяет перетаскивать предметы.
00:00:11
Оно будет отображать
00:00:13
индикатор стека, и оно будет позвольте нам
00:00:16
перетаскивать всю панель по экрану,
00:00:18
и мы собираемся сделать это с помощью набора инструментов пользовательского интерфейса,
00:00:21
но, используя код, а не клики в UI
00:00:23
Builder, мы рассмотрим два
00:00:25
разных способа перетаскивания
00:00:26
с помощью набора инструментов пользовательского интерфейса. способ будет
00:00:29
заключаться в реализации манипулятора набора инструментов пользовательского интерфейса, который нужно
00:00:31
сделать сегодня, так что давайте
00:00:34
начнем с общего
00:00:39
обзора, давайте начнем с быстрого
00:00:41
просмотра диаграммы здесь, так что у меня есть
00:00:43
настройка, очень похожая на видео за две
00:00:45
недели. назад о MVP MVC, поэтому у меня есть
00:00:48
представление о контроллере и модели здесь, в
00:00:51
редакторе Unity, мы собираемся представить
00:00:52
всю систему через моно-
00:00:54
поведение, называемое инвентарем, которое будет иметь доступ
00:00:56
прямо к контроллеру, который
00:00:58
будет иметь контроллер. двусторонний
00:01:00
доступ к модели и представлению, поэтому
00:01:03
модель и представление будут публиковать
00:01:04
события, а контроллер будет принимать все
00:01:06
решения о том, что
00:01:08
произойдет в системе. Я хочу спроектировать свою
00:01:10
систему таким образом, чтобы были
00:01:11
четкие швы между каждой из этих
00:01:13
частей, которые на самом деле должны быть отдельной
00:01:15
маленькой единицей, и сегодня мы собираемся сосредоточиться на
00:01:17
одной из этих частей, и это
00:01:19
точка зрения. Я хочу построить эту систему таким
00:01:21
образом, чтобы в будущем, если я решу Мне
00:01:23
больше не нравится набор инструментов пользовательского интерфейса. Я хочу
00:01:25
снова использовать yugui или хочу использовать
00:01:28
лучшую систему, например Nova. Я должен иметь возможность
00:01:30
заменить весь этот модуль представления
00:01:33
любой системой, которую захочу. Итак, сегодня мы
00:01:34
сосредоточимся именно на этом. одну небольшую
00:01:36
область представления и процедурно создадим
00:01:39
наш пользовательский интерфейс и все необходимое для
00:01:41
функциональности перетаскивания. Сегодня мы
00:01:43
собираемся построить все с помощью кода, но
00:01:44
если вам нужен учебник по использованию UI
00:01:46
Builder, который поставляется с Unity, у меня есть
00:01:48
ссылка на это отличное видео от HJ
00:01:50
at uim motion video в описании,
00:01:52
теперь нам все еще понадобится пустой
00:01:54
XML-документ UX, который будет служить корнем
00:01:56
наших визуальных эффектов, чтобы вы могли получить новый,
00:01:58
создав набор инструментов пользовательского интерфейса. Документ пользовательского интерфейса.
00:02:02
Я просто вызову свой инвентарь,
00:02:04
а затем открою его в
00:02:07
ryer. Если мы посмотрим здесь, вы увидите,
00:02:10
что
00:02:11
с этим uxl связано довольно много метаданных, и большая часть из них
00:02:14
не нужна для этого. документ по умолчанию
00:02:16
также имеет пространство имен движка, если мы
00:02:19
перейдем к одному из этих примеров, это
00:02:21
взято из викторины U, они используют
00:02:23
пространство имен пользовательского интерфейса и имеют совершенно
00:02:25
другие метаданные, теперь мы могли бы фактически использовать
00:02:27
минимум, который будет
00:02:29
выглядеть примерно так вот теперь у меня
00:02:32
вообще нет пространства имен, поэтому я
00:02:33
думаю, что на самом деле я собираюсь
00:02:34
вернуться к своему uxl-документу инвентаризации
00:02:37
и просто удалю
00:02:39
почти все ненужное, что
00:02:41
мы не создавать инструмент редактора, чтобы
00:02:43
эти строки можно было оставить, мы можем
00:02:44
поднять эту строку и избавиться от
00:02:46
объявления версии XML сейчас, если только
00:02:48
вы не собираетесь использовать UI Builder, вы
00:02:50
никогда больше не будете вносить изменения в этот документ,
00:02:52
мы собираюсь сделать все
00:02:53
процедурно и просто использовать это как
00:02:56
корень сейчас, если я вернусь в Unity,
00:02:59
я могу перейти к своему пустому игровому
00:03:02
объекту инвентаря и добавить новый
00:03:04
компонент, и этот компонент
00:03:06
теперь будет документом пользовательского интерфейса. вы можете создать свой
00:03:09
собственный ресурс настроек панели,
00:03:11
создав ресурс настроек панели инструментов пользовательского интерфейса,
00:03:14
но он у меня уже есть, поэтому я просто
00:03:15
выберу свой с помощью селектора,
00:03:17
и нам также нужна ссылка на
00:03:19
документ uxl, который мы только что создали. работая
00:03:21
над каждым документом uxl, вы, вероятно, захотите
00:03:24
также иметь таблицу стилей, чтобы вы могли получить
00:03:26
одну из них, вернувшись в
00:03:27
меню создания, снова перейдите к набору инструментов пользовательского интерфейса
00:03:30
и выберите
00:03:33
таблицу стилей, теперь я буду называть это тем
00:03:35
же именем, что и XML-документ, и
00:03:37
я собираюсь открыть его в Writer, чтобы
00:03:39
мы могли видеть, что в нем определен только один элемент
00:03:41
вообще без стиля, прежде чем
00:03:44
мы начнем писать стили, и, поскольку мы
00:03:45
не используем UI Builder, давайте просто сделаем
00:03:48
немного диаграмма того, чего мы ожидаем,
00:03:50
поэтому давайте вытянем все наши
00:03:53
визуальные элементы один за другим, начиная с
00:03:55
тех, которые расположены ближе всего к корню, поэтому в
00:03:58
самом конце этой стопки у меня будет
00:04:00
контейнер, который просто растянет
00:04:02
весь ширина экрана, а затем в качестве
00:04:05
дочернего элемента у нас будет
00:04:07
настоящий инвентарь, теперь инвентарь
00:04:09
будет находиться между контейнером и
00:04:12
всеми слотами, поэтому мы сможем поместить
00:04:13
на него фоновое изображение и еще много чего но
00:04:16
абсолютно расположен поверх этого
00:04:18
инвентаря. Я хочу иметь рамку и
00:04:20
еще одно маленькое фоновое изображение со
00:04:22
словами «инвентарь», чтобы у нас была
00:04:24
рамка, и я сделаю еще одну, я
00:04:26
просто назову ее здесь как заголовок заголовок
00:04:28
может быть его собственным визуальным элементом, но у нас
00:04:30
может быть его дочерний элемент, который является меткой,
00:04:32
а затем мы можем легко изменить
00:04:34
его текст, поэтому я создам здесь еще один визуальный
00:04:36
элемент, который будет представлять наш
00:04:38
контейнер слотов, поэтому он будет просто быть,
00:04:41
по сути, контейнером-оберткой вокруг всех
00:04:43
слотов и помогать им
00:04:44
правильно позиционироваться. Над остальными
00:04:46
визуальными элементами инвентаря каждый слот
00:04:49
должен содержать немного
00:04:50
логики, поэтому он будет расширять визуальный
00:04:53
элемент и быть отдельным классом. хм, и
00:04:55
это только потому, что все эти
00:04:57
остальные - своего рода пустышки, они просто
00:04:58
заполнители для позиционирования
00:05:00
и стиля, сами слоты должны
00:05:02
содержать немного логики, чтобы они могли
00:05:04
реагировать на события указателя, я просто собираюсь
00:05:06
сложить они здесь, в представлении, в
00:05:08
том порядке, в котором я ожидаю, что они
00:05:10
появятся в моем дереве, и это будет иметь
00:05:12
смысл, когда мы начнем процедурно
00:05:14
собирать всю эту древовидную структуру
00:05:16
визуальных элементов, чтобы слоты располагались
00:05:19
здесь на самом верху, но есть еще
00:05:22
одна вещь, которую мы хотим: это
00:05:24
небольшой значок, который мы можем перетаскивать, поэтому,
00:05:26
как только мы что-то выберем, мы
00:05:28
создадим небольшой значок-призрак, который
00:05:30
большую часть времени будет невидимым, но
00:05:32
как только мы сделаем выбор для перетаскивания
00:05:34
одного из слотов мы собираемся
00:05:36
заполнить его изображением, а затем мы сможем
00:05:37
перетаскивать его по мере
00:05:40
необходимости. Представление хранилища
00:05:42
будет основой этой системы, у него будет
00:05:44
массив, который будет
00:05:46
представлять все слоты в этом
00:05:48
конкретном хранилище сегодня мы
00:05:50
просто работаем над инвентаризацией, но в
00:05:52
будущем у нас будет больше, теперь
00:05:54
потребуется ссылка на
00:05:56
компонент документа пользовательского интерфейса, а также на ту
00:05:59
таблицу St Styles, которую мы созданный следующим. У меня
00:06:01
будет несколько ссылок как на
00:06:03
корневой, так и на его дочерний контейнер,
00:06:06
просто чтобы можно было легко делать запросы позже.
00:06:08
Хорошо иметь ссылку на эти
00:06:10
элементы верхнего уровня. Далее я собираюсь
00:06:12
создать здесь абстрактный метод. он
00:06:14
будет отвечать за создание нашего дерева
00:06:17
визуальных элементов, и я собираюсь передать
00:06:19
аргумент с размером по умолчанию 20.
00:06:22
Теперь я уже знаю, что инвентарь, который мне нужен
00:06:23
сейчас, равен 20, но если я позже использую его для своей горячей панели,
00:06:26
я мог бы сейчас хочу передать 10 или шесть,
00:06:28
я начну с
00:06:30
копрограммы в начале, но в будущем я
00:06:32
запущу ее с контроллера, как только
00:06:34
вся система инвентаризации будет подключена,
00:06:36
этого действительно достаточно для нашего
00:06:38
хранилища на данный момент давайте расширим его
00:06:40
с помощью класса представления инвентаря, давайте
00:06:43
избавимся от этой красной волнистой линии,
00:06:45
реализовав метод инициализированного представления,
00:06:47
теперь инициализированное представление будет делать
00:06:49
все необходимое для настройки визуального
00:06:51
дерева для нас и инициализации наших слотов,
00:06:53
потому что мы у нас будет метка в
00:06:55
верхней части этой конкретной панели. Я
00:06:58
просто собираюсь представить ее в виде строки
00:07:00
редактору Unity здесь с
00:07:01
сериализованным полем в качестве первого порядка
00:07:04
действий. Здесь давайте просто определим наш
00:07:06
массив как новый массив размер, который
00:07:09
мы сейчас передали из нашего документа пользовательского интерфейса,
00:07:12
мы можем получить корневой визуальный элемент и
00:07:14
назначить его корневой переменной, и
00:07:16
я просто собираюсь запустить root. CLE здесь,
00:07:18
который будет очищать это каждый раз, когда мы
00:07:20
решаем инициализировать представление на случай, если
00:07:21
мы по какой-то причине запускаем его несколько раз, у
00:07:23
нас также будет
00:07:24
ссылка на таблицу стилей, поэтому давайте
00:07:26
применим ее к корню, теперь мы можем начнем
00:07:28
создавать остальную часть дерева, поэтому
00:07:30
мы начнем с контейнера,
00:07:31
который будет растягиваться
00:07:33
по всему экрану, и я собираюсь использовать
00:07:35
метод расширения, создайте дочерний элемент, теперь
00:07:37
этот метод расширения и несколько других,
00:07:39
которые я которые будут использоваться,
00:07:40
подробно обсуждались на нашем
00:07:42
канале Discord, к которому вы можете присоединиться. Я
00:07:44
уверен, что у нас будет еще много
00:07:45
интересных разговоров о пользовательском интерфейсе и
00:07:47
системах инвентаря, почему бы нам не пойти
00:07:50
и не взглянуть в этих
00:07:51
расширениях прямо сейчас основная цель
00:07:53
всех этих пользовательских методов расширения -
00:07:55
сделать так, чтобы мы могли объединять методы
00:07:57
вместе и иметь меньше кода,
00:08:00
когда мы конструируем вещи
00:08:01
процедурно, чтобы мы могли создавать
00:08:03
дочерние элементы и прикреплять их родителям, у меня
00:08:05
есть два метода: один
00:08:06
специально для визуальных элементов, а другой
00:08:08
для любого типа. Т.е. мы также можем
00:08:11
добавить определенный дочерний элемент к родительскому элементу, мы
00:08:14
можем добавить стиль класса CSS к
00:08:17
визуальному элементу и если мы прокрутим немного вниз,
00:08:19
мы также сможем добавить
00:08:21
манипулятор к определенному элементу,
00:08:24
мы доберемся до манипуляторов ближе к
00:08:26
концу этого видео, весь этот код будет
00:08:28
в репозитории, чтобы вы могли просмотреть его
00:08:29
позже,
00:08:31
давайте продолжим создадим первого
00:08:34
дочернего элемента нашего контейнера, который
00:08:36
будет задней панелью инвентаря, чтобы мы могли
00:08:39
создать дочерний элемент в контейнере и
00:08:41
присвоить ему стиль
00:08:43
инвентаря, у инвентаря будет
00:08:45
два дочерних элемента, что будет абсолютно
00:08:47
расположим это фрейм, а
00:08:49
поверх него будет заголовок, у
00:08:51
заголовка будет собственный
00:08:52
дочерний элемент, который является меткой, и метка
00:08:55
будет иметь имя панели инвентаря,
00:08:57
следующее по порядку будет в
00:08:59
контейнере слотов I Я собираюсь сделать его дочерним элементом
00:09:01
инвентаря и присвоить ему стиль
00:09:03
под названием slotsContainer. Теперь мы можем
00:09:05
перебирать размер и создадим
00:09:07
новый слот, который будет дочерним элементом
00:09:09
контейнера слота. slot — это класс, который
00:09:11
расширяет визуальный элемент. элемент, теперь он действует так же,
00:09:14
как визуальный элемент, но у него будет
00:09:16
дополнительная логика для нас, мы
00:09:18
дадим каждому из них класс слота, а
00:09:20
затем я также хочу отслеживать его в
00:09:22
своем массиве слотов, теперь мы почти закончили
00:09:25
построение нашего дерева, если мы сделаем быстрый
00:09:26
шаг назад и просто посмотрим на все это,
00:09:28
вы увидите, что мы собираем
00:09:30
его постепенно, причем один элемент становится
00:09:33
родственным или дочерним элементом следующего, и
00:09:36
мы даем большую часть из них у вещей свое
00:09:37
собственное имя стиля, мы собираемся перейти к
00:09:40
стилизации через минуту, а теперь давайте
00:09:42
посмотрим на этот класс слота, который расширяет
00:09:44
визуальный элемент. Мне нужно, чтобы каждый слот знал
00:09:47
немного информации, но на самом деле это
00:09:49
не обязательно знать много о
00:09:51
реальном элементе: он должен показывать
00:09:53
пользователю красивые картинки, чтобы он мог щелкать
00:09:55
по ним и перемещать их, поэтому ему нужно
00:09:57
знать, какое изображение нужно показывать, и я также
00:10:00
собираюсь показать метку стека, поэтому, если мы
00:10:03
собираем стопку элементов, и у нас есть счетчик
00:10:05
больше единицы. Я хочу иметь
00:10:06
возможность показать пользователю, сколько их на
00:10:08
самом деле находится в слоте. Далее я
00:10:10
собираюсь использовать индекс метода,
00:10:13
который существует для визуальных элементов, и поскольку
00:10:15
каждый визуальный элемент также имеет
00:10:16
ссылку на своего родителя, и этот родительский элемент,
00:10:19
являющийся контейнером слотов, содержит только
00:10:21
слоты, индекс метода фактически
00:10:23
даст нам правильный номер
00:10:25
этого слота в контейнере слотов, поэтому
00:10:27
первый будет нулевым, и
00:10:29
он будет идти вплоть до 19, теперь для
00:10:31
удобства мы также собираемся передать
00:10:33
немного данных о том, что должно
00:10:35
отображаться здесь на экране. Первое — это
00:10:37
сериализуемый товар, к которому мы
00:10:39
вернемся в следующем видео.
00:10:41
представляющий тип элемента, который
00:10:43
является другим, будет фактическим
00:10:46
спрайтом, который также исходит из деталей элемента,
00:10:48
и это потому, что изображение и
00:10:49
спрайт на самом деле не одно и то же, мне
00:10:51
нужно применить текстуру из спрайта
00:10:53
к изображению, поэтому мне полезно
00:10:56
сохранить ссылку на это здесь, чтобы в
00:10:59
инструкторе я мог создать другие визуальные
00:11:00
элементы, которые нам нужны. Я собираюсь
00:11:01
создать здесь три из них, но мне
00:11:03
нужны ссылки только на два из них, потому что
00:11:04
один посередине кадр слота,
00:11:07
который будет располагаться поверх
00:11:09
изображения, но под счетчиком стека, теперь,
00:11:12
наконец, нам нужен способ фактически установить
00:11:14
это с контроллера, чтобы мы могли поместить
00:11:16
сюда наши фиктивные элементы для тестирования, и
00:11:19
мы, конечно, во время выполнения мы мы
00:11:21
также захотим установить и отключить это,
00:11:23
поэтому у нас просто будет метод
00:11:25
под названием set, который будет принимать наш
00:11:26
сериализуемый товар Sprite и
00:11:29
количество, если оно отличается от
00:11:31
нуля, поэтому мы установим идентификатор элемента в
00:11:34
базовый спрайт - это единственные данные, которые нас
00:11:36
действительно волнуют, затем мы собираемся
00:11:38
установить изображение значка, если базовый спрайт
00:11:41
не равен нулю, давайте получим текстуру из этого,
00:11:44
в противном случае это ноль, изображение не будет отображаться, а
00:11:47
затем мы можем сказать метку стека текст, если
00:11:49
количество больше единицы, давайте
00:11:52
поместим туда количество, в противном случае
00:11:54
пустая строка, а затем мы решим,
00:11:56
видимо оно или нет, также в зависимости от того,
00:11:57
больше ли количество единицы,
00:12:00
теперь у нас также должен быть метод, чтобы
00:12:02
очистить это и все, что нужно сделать,
00:12:04
это установить пустой идентификатор и установить для изображения
00:12:07
нулевое значение, вот и все, нам, вероятно, следует
00:12:10
что-то сделать и с нашим призрачным значком,
00:12:12
потому что мы собираемся применить
00:12:13
к нему немного стиля, поэтому
00:12:15
если я снова перейду сюда к представлению хранилища,
00:12:17
давайте просто создадим статический визуальный
00:12:20
элемент, который будет представлять
00:12:22
значок призрака, теперь мы можем инициализировать его, когда
00:12:24
инициализируем остальную часть нашего дерева,
00:12:26
так что вернемся сюда, в представление инвентаря, я просто
00:12:29
добавлю один больше строк, чтобы мы могли
00:12:31
инициализировать этот призрачный элемент как
00:12:33
дочерний элемент контейнера, и я собираюсь
00:12:35
дать ему имя стиля, называемое призрачным значком.
00:12:38
Я также собираюсь использовать метод «Перенести на передний план»,
00:12:40
этот метод гарантирует, что
00:12:43
конкретный визуальный элемент будет
00:12:45
перед всеми своими братьями и сестрами. Итак,
00:12:48
мы построили все наше дерево, почему бы
00:12:50
нам не взглянуть на него и не посмотреть, как
00:12:52
оно выглядит без какого-либо стиля, так что
00:12:55
вернемся сюда, в единстве, которое мне нужно чтобы добавить это
00:12:57
представление инвентаря к игровому
00:13:00
объекту инвентаря, как только я его получу, ему
00:13:02
нужно несколько ссылок, первой из которых
00:13:03
является этот документ пользовательского интерфейса, я просто
00:13:05
перетащу эту ссылку туда, тогда ему
00:13:07
нужна ссылка на этот пустой
00:13:08
таблица стилей, которую мы
00:13:10
сейчас начнем заполнять. Кроме того, мне также нужен
00:13:13
сам компонент инвентаря, который выполняет
00:13:15
всю проводку контроллера,
00:13:17
модели и представления вместе и
00:13:18
предоставит наши стартовые
00:13:20
элементы, которые я уже создал.
00:13:21
несколько здесь, так что я просто перетащу
00:13:23
их сюда и хочу еще
00:13:25
парочку, чтобы мы могли
00:13:27
также проверить штабелирование, может быть, я
00:13:29
возьму еще один гриб, и этого
00:13:31
должно быть достаточно, чтобы получить мы начали, но
00:13:33
что происходит, когда мы нажимаем кнопку воспроизведения, теперь
00:13:36
давайте выясним, чтобы все наши элементы
00:13:38
отображались в красивом столбце, и это здорово,
00:13:40
но как мы без каких-либо стилей узнаем,
00:13:43
что эта структура на самом деле правильная, а у
00:13:45
Unity на самом деле есть
00:13:47
довольно хороший инструмент и это называется
00:13:48
отладчиком в отладчике, там есть
00:13:51
кнопка, называемая элементом выбора, и я
00:13:52
могу выбрать что-то на экране, чтобы
00:13:53
посмотреть, поэтому теперь я выбрал
00:13:56
здесь все свое дерево и могу взглянуть
00:13:58
на точную его структуру где
00:14:01
применяются классы, и я могу разбить его
00:14:03
полностью здесь, вплоть до метки
00:14:05
стека, чтобы он выглядел хорошо, я вижу
00:14:08
свой значок призрака там внизу,
00:14:09
так как это выглядит именно так, как я
00:14:12
предполагал, давайте начнем
00:14:13
немного применять немного стиля, постепенно, просто в
00:14:16
порядке обзора, давайте вернемся к нашему uxl-
00:14:19
документу, вы можете видеть, что здесь ничего нет, но
00:14:21
это просто корень,
00:14:23
больше ничего нет и никогда не будет, теперь
00:14:25
в нашей пустой таблице стилей давайте начнем
00:14:27
работать с самый низ,
00:14:29
который будет контейнером, и мы идем
00:14:31
до самого верхнего элемента, поэтому
00:14:33
контейнер будет каскадировать свои
00:14:36
стили ко всему остальному, поэтому мне нравится
00:14:38
размещать здесь вещи, которые я
00:14:39
обычно хочу установить повсюду,
00:14:41
это Flex увеличить один, мы хотим, чтобы ширина
00:14:43
и высота были автоматическими, без максимальных значений, я
00:14:47
просто хочу, чтобы столбец был по
00:14:48
умолчанию, мы собираемся выровнять
00:14:50
все по вертикали и горизонтали
00:14:53
в середине. Я выбрал шрифт, который
00:14:55
поставляется с этим активом. package и указал
00:14:57
его здесь как наш шрифт по умолчанию для
00:14:59
всего, я собираюсь добавить немного
00:15:01
тени, а затем я также выбрал
00:15:03
желтый цвет, который вы можете увидеть в столбце,
00:15:05
где автор также показывает мне, что это за
00:15:07
цвета, теперь я Перейду к
00:15:09
инвентарю, в инвентаре будет показан
00:15:12
наш фон, представляющий собой красивую деревянную
00:15:13
панель. Я хочу, чтобы он был фиксированного размера для
00:15:16
меня. Я знаю, что я хочу, чтобы этот инвентарь
00:15:18
был шириной 300 пикселей и высотой не более 500
00:15:22
пикселей. Я добавил туда немного отступов,
00:15:24
чтобы я мог держать содержимое
00:15:25
подальше от краев, давайте посмотрим, и у нас появилась
00:15:29
деревянная панель, и
00:15:31
теперь мы можем видеть там слова «инвентаризация»,
00:15:33
хотя она находится не в том месте, но
00:15:36
вы знаете, что это выглядит
00:15:37
неплохо, давайте продолжим здесь, давайте
00:15:41
что-нибудь сделаем с этим текстом, поэтому для
00:15:43
класса заголовка инвентаря я собираюсь
00:15:45
расположить его абсолютно. Я уже
00:15:47
точно знаю, где он сейчас, помните, что
00:15:49
абсолютное позиционирование относится к
00:15:51
родительскому элементу, а не ко всему документ, так что он
00:15:53
относится к инвентарю, а не к
00:15:56
контейнеру или чему-то над ним, поэтому я знаю
00:15:58
позиции, которые я хочу, чтобы он был центрирован. У меня
00:16:01
есть хорошее фоновое изображение, которое я собираюсь
00:16:02
поместить под это, а теперь обратите внимание на
00:16:04
последнее, что здесь единый масштаб срезов,
00:16:07
когда вы используете девять нарезанных изображений,
00:16:09
иногда они могут выглядеть шатко, если они
00:16:11
слишком велики для того, что вы пытаетесь сделать,
00:16:13
вы можете уменьшить или увеличить их, используя этот
00:16:15
атрибут, теперь я собираюсь добавить один
00:16:17
здесь еще кое-что для метки, я хочу, чтобы текст
00:16:19
был больше, давайте проверим это сейчас,
00:16:22
обратите внимание, я все еще в режиме воспроизведения. Я никогда не
00:16:23
выходил из режима воспроизведения. Я просто возвращаюсь
00:16:25
в редактор и нажимаю контроллер. Я
00:16:27
вижу свой ch в реальном времени. время, это одна из
00:16:30
прекрасных особенностей набора инструментов пользовательского интерфейса, так что
00:16:33
это выглядит довольно хорошо, давайте
00:16:34
продолжим оформление, если я вернусь
00:16:37
сюда, я собираюсь добавить
00:16:39
рамку инвентаря, здесь нет сюрпризов, это почти то
00:16:41
же самое, что и заголовок, просто другое
00:16:43
изображение и разные размеры, давайте сделаем
00:16:45
быструю проверку
00:16:47
crlr, которая выглядит довольно хорошо, давайте перейдем
00:16:49
к контейнеру слота и фактическим
00:16:51
слотам, контейнер слота должен быть
00:16:54
немного вниз сверху, поэтому я
00:16:55
добавил туда немного отступов, которые нужно
00:16:57
обернуть и он должен идти рядами, начиная
00:17:00
с верхнего левого угла, поэтому у
00:17:03
меня есть Flex Start для выравнивания элементов
00:17:05
и выравнивания элементов теперь для каждого слота, который я знаю, я
00:17:08
хочу иметь определенный размер, а это
00:17:10
60x60 с запасом в четыре вокруг
00:17:14
каждого слота сверху над каждым слотом есть рамка, которую
00:17:16
необходимо расположить абсолютно точно. Он
00:17:18
одинакового размера расположен сверху
00:17:21
слева, и у меня уже есть изображение, чтобы
00:17:23
войти в него, а дальше здесь у нас есть
00:17:26
настоящий значок слота, теперь я' Я не собираюсь
00:17:29
указывать размер, я просто хочу, чтобы он поместился
00:17:31
в слот, теперь рамка, которая поставляется
00:17:33
с этим липким ресурсом, имеет небольшие закругленные
00:17:35
углы, поэтому я хочу добавить немного
00:17:38
отступов, чтобы мои изображения моих
00:17:40
значков не выступают за рамку, но
00:17:43
когда мы вытащим их оттуда, у них
00:17:45
больше не будет набивки, так что это
00:17:46
будет выглядеть круто, если они будут
00:17:47
немного больше, давайте
00:17:49
посмотрим, как у нас дела обстоят на данный момент ну, это
00:17:51
выглядит как настоящая панель инвентаря, теперь
00:17:53
это не так уж и плохо, конечно, мы ничего не можем с этим сделать,
00:17:57
перетаскивания пока нет, но мы доберемся до этого через
00:18:00
мгновение, прежде чем начнем делать
00:18:02
падение дракона, давайте сделаем уверен, что у нас
00:18:03
есть подходящие стили для всего остального, поэтому
00:18:05
значок призрака должен быть того же размера,
00:18:07
что и слот. Я просто вставлю его
00:18:09
сюда, это абсолютная вещь, которую
00:18:11
мы собираемся перетаскивать и менять
00:18:12
ее положение. Если мы начнем его как скрытое,
00:18:15
давайте также добавим стили только для
00:18:17
стека, счетчик стека также
00:18:19
будет абсолютным, но он начинается в
00:18:20
правом нижнем углу и будет
00:18:23
поверх этого кадра, и его просто
00:18:25
нужно немного меньший размер, поэтому,
00:18:27
очевидно, мне пришлось немного повозиться, чтобы
00:18:28
выяснить все числа,
00:18:30
расположение, размеры и все такое, но
00:18:32
с изменениями во время выполнения это действительно не
00:18:34
так уж и плохо, мы не сможем протестировать ни один
00:18:36
из этих двух последних стилей, пока мы
00:18:38
реализовали Drop Drop, поэтому давайте перейдем
00:18:40
к этому, поэтому вернемся к классу представления хранилища.
00:18:43
Я собираюсь добавить еще два поля,
00:18:45
одно из которых является логическим, чтобы сказать,
00:18:47
перетаскиваем мы или нет, другое будет
00:18:49
хранить ссылку в слот, который
00:18:51
сейчас перетаскивается, все визуальные
00:18:54
элементы позволяют вам регистрировать обратные
00:18:56
вызовы, поэтому я собираюсь зарегистрировать
00:18:58
обратный вызов здесь для событий указателя вниз, поэтому,
00:19:00
когда игрок нажимает на этот слот, я хочу
00:19:03
опубликовать событие, которое событие будет
00:19:05
опубликуйте местоположение указателя, и
00:19:07
это сообщит нам, какой слот
00:19:09
на самом деле был нажат, чтобы запустить это событие,
00:19:12
давайте напишем здесь метод on указателя вниз,
00:19:15
мы можем сказать, была ли это самая
00:19:16
левая кнопка или идентификатор элемента
00:19:19
на самом деле является пустым руководством давайте вернемся
00:19:21
раньше, иначе запустим отправку события
00:19:24
в позицию и ссылку на этот
00:19:26
слот, наконец, давайте остановим распространение
00:19:29
события, потому что мы не хотим, чтобы другие
00:19:30
элементы в дереве реагировали на это
00:19:33
конкретное событие, которое мы уже обработали,
00:19:34
если вернемся назад в представлении хранилища мы
00:19:37
можем прослушивать эти события здесь, поэтому в
00:19:39
нашем методе запуска почему бы нам не зарегистрировать
00:19:41
прослушиватель для каждого из слотов. Я могу
00:19:43
просто создать цикл for здесь, и я
00:19:44
зарегистрирую
00:19:45
каждое, теперь у нас будет метод который будет
00:19:48
обрабатывать это, когда одно из событий из
00:19:50
слота будет запущено, мы вызовем это при
00:19:51
указателе вниз, поэтому указатель вниз будет
00:19:54
обрабатывать оба этих аргумента,
00:19:56
позицию и слот, поэтому здесь мы можем
00:19:59
реализовать всю нашу логику, чтобы что-то вроде перенесем
00:20:01
информацию из слота в
00:20:03
призрачный значок, чтобы мы установили для параметра перетаскивания значение
00:20:06
true, и давайте установим исходный слот
00:20:08
как этот слот на случай, если нам понадобится
00:20:09
вернуться к нему позже. Я собираюсь
00:20:11
создать небольшой вспомогательный метод. Здесь это
00:20:13
поможет нам перемещать значок призрака.
00:20:16
Помните, что он абсолютно позиционирован,
00:20:18
поэтому мне нужно переместить его в соответствии с его стилем, поэтому
00:20:20
давайте воспользуемся этим методом здесь. Теперь, когда
00:20:23
мы правильно установили положение нашего значка призрака,
00:20:25
мы можем обновить его фоновое
00:20:26
изображение на это текст спрайта, мы
00:20:29
можем установить исходное изображение слота на ноль
00:20:32
и можем скрыть индикатор стека,
00:20:34
наконец, давайте применим немного
00:20:35
стилей к значку призрака, мы определенно
00:20:37
хотим, чтобы он был видимым, и мы могли бы сделать
00:20:40
его немного полупрозрачным. -opaque, но я думаю, что
00:20:43
сначала я поиграю с этим немного и посмотрю, действительно ли мне это нравится,
00:20:45
и это действительно может войти в
00:20:46
таблицу стилей, вы знаете, честно говоря, есть еще
00:20:48
два события, которые нужно обработать, которые
00:20:49
перемещаются и что Собираемся ли мы
00:20:51
делать, когда игрок действительно бросает
00:20:53
элемент, мы не хотим, чтобы наше представление принимало какие-либо
00:20:55
логические решения о том,
00:20:57
принадлежит ли этот элемент модели или
00:21:00
нет, поэтому мы собираемся опубликовать
00:21:02
событие с исходный слот, а
00:21:04
пункт назначения — целевой слот, и мы можем
00:21:07
заставить наш контроллер прослушивать это, и
00:21:08
он будет принимать решения, поэтому мы получили
00:21:10
это событие там, теперь мы не можем регистрировать
00:21:13
эти обратные вызовы для моно-поведения, но у нас
00:21:16
здесь есть статический визуальный элемент,
00:21:18
который это значок-призрак, мы можем зарегистрировать
00:21:20
обратные вызовы прямо на него, поскольку у нас есть
00:21:22
статическая ссылка на значок-призрак
00:21:24
здесь, в этом классе, мы также можем обрабатывать
00:21:27
любые события, которые перехватываются прямо здесь, в
00:21:29
этом классе, поэтому давайте прокрутим немного вниз
00:21:31
и есть обработчики для
00:21:33
перемещения указателя onp и указателя onp вверх,
00:21:36
давайте сначала сделаем перемещение, потому что это
00:21:38
довольно просто, если мы не
00:21:40
перетаскиваем залог отсюда, в противном случае
00:21:42
давайте просто обновим позицию, используя наш
00:21:44
вспомогательный метод, который
00:21:46
достаточно прост, один указатель вверх - это немного немного
00:21:48
сложнее, я просто снова оставлю себе
00:21:50
немного места, если мы
00:21:52
не будем перетаскивать, нет смысла находиться
00:21:54
внутри этого метода, давайте выйдем из строя, теперь
00:21:56
мы собираемся использовать некоторую ссылку, чтобы выяснить,
00:21:58
какой слот на самом деле был
00:22:00
Ближайшие к нашей точке перетаскивания визуальные
00:22:03
элементы имеют свойство
00:22:05
Worldbound, и мы можем использовать для них метод,
00:22:07
который называется перекрытием. Это даст
00:22:09
нам бесчисленное множество всех слотов, которые
00:22:11
перекрывают значок призрака, мы
00:22:14
упорядочим их по ближайшему значению. до самого дальнего
00:22:17
расстояния, а затем мы можем получить первый слот или
00:22:19
по умолчанию, который даст нам ближайший слот
00:22:21
к точке сброса, пока он
00:22:24
не был нулевым, мы действительно можем вызвать наш
00:22:26
CU события, мы знаем, каким был исходный SL,
00:22:28
и мы знаем каким был наш целевой слот,
00:22:30
который будет ближайшим слотом, если
00:22:32
мы не собираемся вызывать это событие,
00:22:34
давайте просто сбросим исходный значок слота,
00:22:36
чтобы как будто ничего не произошло, как
00:22:38
будто мы бросили его в никуда, теперь
00:22:41
мы можем отключить перетаскивание мы также можем установить
00:22:44
исходный слот обратно на ноль, он нам
00:22:45
больше не нужен, и мы можем скрыть
00:22:47
значок призрака. Думаю, пришло время для
00:22:49
небольшого теста. Если мы вернемся сюда,
00:22:52
перезагрузим домен и нажмем «Play», вуаля,
00:22:55
посмотрим, окей,
00:22:58
гриб выходит кальмар выходит
00:23:01
стопка грибов, и мы видим две, мы можем
00:23:03
сложить их до трех, я могу поменять этого
00:23:06
на кости, посмотрим, я могу поменять местами
00:23:09
эти кальмары, да,
00:23:14
в моем манекене ничего не произойдет, подробности о грибах
00:23:16
являются единственными, которым разрешено
00:23:18
штабелирование, поэтому они ведут себя
00:23:19
таким образом: кальмары будут просто меняться местами друг
00:23:22
с другом, ладно, последнее, что нужно сделать, это
00:23:24
иметь возможность перемещать всю эту панель,
00:23:26
давайте еще раз посмотрим на эти
00:23:29
методы расширения, теперь с
00:23:31
Метод расширения манипулятора просто
00:23:33
запускает обычный метод рекламного манипулятора,
00:23:35
за исключением того, что он вернет нам
00:23:37
визуальные элементы, чтобы мы могли
00:23:38
объединить их вместе,
00:23:40
чтобы использовать его, нам действительно нужно
00:23:42
создать манипулятор, это на самом деле
00:23:44
намного проще, чем вы могли бы подумайте, я
00:23:46
создал здесь класс, который наследует от
00:23:48
манипулятора указателей, и это
00:23:50
позволит нам использовать все те
00:23:52
обратные вызовы, которые мы регистрируем для
00:23:54
визуальных элементов раньше, но мы можем обернуть
00:23:57
их в такой симпатичный маленький класс, как этот
00:23:59
так что он станет небольшим мини-конечным
00:24:01
автоматом. Я просто импортирую
00:24:03
сюда недостающие элементы, которые должны регистрироваться и
00:24:06
отменять регистрацию для обратных вызовов. Я просто
00:24:08
вставлю их прямо сюда, нам нужны все
00:24:10
три тех же обратных вызова, которые мы
00:24:12
использовали для падение дракона, но на этот
00:24:15
раз мы собираемся собрать их в симпатичную
00:24:16
маленькую упаковку, здесь целью будет то, к чему
00:24:18
мы применим этот манипулятор,
00:24:20
и это будет
00:24:22
панель инвентаря. У манипуляторов также есть что-то,
00:24:24
называемое активатором, и я собираюсь
00:24:26
создать его прямо сейчас активатор - это
00:24:28
условие, при котором этот манипулятор
00:24:31
решает, может ли он работать или нет здесь
00:24:33
я просто добавлю один активатор и
00:24:35
это фильтр, который определяет,
00:24:38
нажал ли игрок
00:24:40
сейчас левую кнопку мыши или нет есть все виды
00:24:42
активаторов, которые вы можете использовать, это
00:24:44
достаточно просто для этого примера, мы собираемся
00:24:46
использовать его в нашем первом обратном вызове, поэтому
00:24:48
давайте начнем с события указателя вниз.
00:24:51
Я также собираюсь добавить пару полей,
00:24:52
просто чтобы отслеживать вещи, пока мы перемещаем
00:24:54
панель, это логическое значение для
00:24:57
перетаскивания и вектор 2
00:24:59
смещения теперь в методе onp указатель вниз,
00:25:02
что мы можем сначала сделать, это проверить
00:25:05
условия наших активаторов,
00:25:08
разрешено ли нам фактически выполнить это событие,
00:25:11
если по какой-то причине флаг is перетаскивание
00:25:12
также верен, и это будет условием
00:25:14
для раннего выхода из системы. Теперь давайте установим
00:25:16
эти два поля, смещение
00:25:18
будет там, где мы начали перетаскивание, а затем
00:25:21
давайте включим флаг, теперь давайте
00:25:23
фактически зафиксируем этот указатель, что это
00:25:24
происходит, когда цель захватывает
00:25:26
указатель, все события указателя отправляются
00:25:29
этому элементу независимо от того, какой
00:25:31
элемент находится под указателем, мы также можем
00:25:33
остановить распространение этого события, потому что
00:25:35
нам не нужны другие элементы в дереве, которые
00:25:37
действительно пытаются обработать это событие,
00:25:39
цель манипулятора будет выполнять
00:25:41
обработку, теперь этот манипулятор будет
00:25:43
работать с любым визуальным элементом, но в нашем
00:25:45
случае целью будет
00:25:47
панель инвентаря, давайте перейдем к
00:25:49
следующему методу для перемещения указателя,
00:25:51
это на самом деле красиво
00:25:52
тоже просто, давайте начнем с
00:25:54
некоторых основных положений защиты, если мы не
00:25:56
перетаскиваем, убирайтесь отсюда, если мы не
00:25:59
захватили указатель, уходите отсюда,
00:26:00
мы выйдем раньше, иначе давайте на
00:26:03
самом деле переместим эту цель, давайте
00:26:06
выясним, что такое Дельта находится между
00:26:08
локальной позицией события и
00:26:10
смещением, и мы просто собираемся применить
00:26:11
это к позиции преобразования цели,
00:26:14
тогда мы также можем остановить распространение события
00:26:16
здесь, а окончательный обработчик примерно так же
00:26:19
прост, давайте еще раз, давайте введем
00:26:21
несколько защитных предложений здесь, в начале, поэтому
00:26:24
невозможно остановить манипуляцию, это своего рода
00:26:26
противоположность возможности запуска манипулирования, поэтому,
00:26:28
если что-то из этого не соответствует действительности, давайте
00:26:31
уйдем отсюда, иначе перетаскивание
00:26:33
станет ложным, а затем мы также можем
00:26:36
освободить указатель от цели и
00:26:37
снова остановить распространение событий, мы
00:26:39
закончили с перетаскиванием, так что это немного
00:26:42
проще, чем
00:26:44
перетаскивание для слотов, но здесь мы
00:26:46
можем просто применить его к одному визуальному элементу, в
00:26:48
слотах определенно было гораздо больше
00:26:50
движущихся частей, но как можем ли мы на самом деле
00:26:53
заставить это работать с целью? Хорошо,
00:26:56
давайте снова перейдем к представлению инвентаря,
00:26:58
и это просто, потому что у нас уже
00:27:00
есть метод расширения для этого,
00:27:02
когда мы создаем наш инвентарь, мы
00:27:04
можем просто связать его снова с помощью
00:27:07
метода расширения манипулятора. и добавьте
00:27:09
новый манипулятор перетаскивания панели в
00:27:12
инвентарь, это все, что вам нужно хорошо сделать,
00:27:15
кроме тестирования, конечно, давайте
00:27:17
пойдем посмотрим, если я перезагружу домен
00:27:19
и нажму кнопку
00:27:21
воспроизведения, проверьте это, я могу взять его где
00:27:24
угодно, где есть разве слот не
00:27:27
заполнен, и перетащите эту штуку куда
00:27:28
захочу, если я возьму слот, конечно, это
00:27:30
будет иметь
00:27:32
приоритет, и все работает так, как
00:27:35
я ожидаю, настолько идеально, что я пока доволен этим,
00:27:38
поэтому надеюсь, что вы чему-то научились
00:27:41
или, может быть, сегодня есть еще что-то новое,
00:27:43
мы продолжим на следующей неделе,
00:27:45
где мы углубимся в контроллер и
00:27:47
модель этой системы инвентаризации, весь
00:27:49
код для этого проекта будет связан
00:27:51
в описании, а также активы,
00:27:54
которые я Я использовал, не стесняйтесь оставлять сообщения в
00:27:56
комментариях, если у вас есть какие-либо мысли или
00:27:58
вопросы или что-то, что вы хотите увидеть
00:28:00
в ближайшие недели, не стесняйтесь присоединяться к
00:28:02
обсуждениям на нашем сервере Discord,
00:28:04
а если вы еще этого не сделали, нажмите на
00:28:07
это поставь лайк, подпишись и нажми на
00:28:09
колокольчик, чтобы не пропустить выпуск на следующей неделе,
00:28:10
увидимся там

Описание:

Learn how to use UI Toolkit like a BOSS in this step by step walkthrough of building a Drag and Drop Inventory System procedurally in Unity using UI Toolkit and some of it's more advanced features such as Activators and Manipulators. 🔔 Subscribe for more Unity Tutorials https://www.youtube.com/@git-amend UI Builder Primer: https://www.youtube.com/@UIMotionEffects Discord: https://discord.com/invite/FDRZGQBBUC ▬ Contents of this video ▬▬▬▬▬▬▬▬▬▬ 0:00 Setup 05:40 Procedural UI 14:15 Styles 18:40 Drag and Drop 23:20 Manipulator *Source code:* https://github.com/adammyhre/Unity-Inventory-System Assets Shown In This Video (Affiliate Links) Misty Fantasy Village : https://assetstore.unity.com/packages/3d/environments/fantasy/misty-fantasy-village-265702?aid=1101lw3sv Cartoon Fantasy UI: https://assetstore.unity.com/packages/2d/gui/cartoon-fantasy-gui-74743?aid=1101lw3sv Eole Foliage Shader: https://assetstore.unity.com/packages/vfx/shaders/eole-stylized-foliage-shaders-265842?aid=1101lw3sv Dungeon Mason Tiny Hero Duo: (FREE): https://assetstore.unity.com/packages/3d/characters/humanoids/rpg-tiny-hero-duo-pbr-polyart-225148?aid=1101lw3sv Kronnect Beautify: https://assetstore.unity.com/packages/vfx/shaders/fullscreen-camera-effects/beautify-3-advanced-post-processing-233073?aid=1101lw3sv *Follow me!* https://linktr.ee/gitamend

Готовим варианты загрузки

popular icon
Популярные
hd icon
HD видео
audio icon
Только звук
total icon
Все форматы
* — Если видео проигрывается в новой вкладке, перейдите в неё, а затем кликните по видео правой кнопкой мыши и выберите пункт "Сохранить видео как..."
** — Ссылка предназначенная для онлайн воспроизведения в специализированных плеерах

Вопросы о скачивании видео

mobile menu iconКак можно скачать видео "Build Procedural UI with Callbacks and Manipulators"?mobile menu icon

  • Сайт http://unidownloader.com/ — лучший способ скачать видео или отдельно аудиодорожку, если хочется обойтись без установки программ и расширений. Расширение UDL Helper — удобная кнопка, которая органично встраивается на сайты YouTube, Instagram и OK.ru для быстрого скачивания контента.

  • Программа UDL Client (для Windows) — самое мощное решение, поддерживающее более 900 сайтов, социальных сетей и видеохостингов, а также любое качество видео, которое доступно в источнике.

  • UDL Lite — представляет собой удобный доступ к сайту с мобильного устройства. С его помощью вы можете легко скачивать видео прямо на смартфон.

mobile menu iconКакой формат видео "Build Procedural UI with Callbacks and Manipulators" выбрать?mobile menu icon

  • Наилучшее качество имеют форматы FullHD (1080p), 2K (1440p), 4K (2160p) и 8K (4320p). Чем больше разрешение вашего экрана, тем выше должно быть качество видео. Однако следует учесть и другие факторы: скорость скачивания, количество свободного места, а также производительность устройства при воспроизведении.

mobile menu iconПочему компьютер зависает при загрузке видео "Build Procedural UI with Callbacks and Manipulators"?mobile menu icon

  • Полностью зависать браузер/компьютер не должен! Если это произошло, просьба сообщить об этом, указав ссылку на видео. Иногда видео нельзя скачать напрямую в подходящем формате, поэтому мы добавили возможность конвертации файла в нужный формат. В отдельных случаях этот процесс может активно использовать ресурсы компьютера.

mobile menu iconКак скачать видео "Build Procedural UI with Callbacks and Manipulators" на телефон?mobile menu icon

  • Вы можете скачать видео на свой смартфон с помощью сайта или pwa-приложения UDL Lite. Также есть возможность отправить ссылку на скачивание через QR-код с помощью расширения UDL Helper.

mobile menu iconКак скачать аудиодорожку (музыку) в MP3 "Build Procedural UI with Callbacks and Manipulators"?mobile menu icon

  • Самый удобный способ — воспользоваться программой UDL Client, которая поддерживает конвертацию видео в формат MP3. В некоторых случаях MP3 можно скачать и через расширение UDL Helper.

mobile menu iconКак сохранить кадр из видео "Build Procedural UI with Callbacks and Manipulators"?mobile menu icon

  • Эта функция доступна в расширении UDL Helper. Убедитесь, что в настройках отмечен пункт «Отображать кнопку сохранения скриншота из видео». В правом нижнем углу плеера левее иконки «Настройки» должна появиться иконка камеры, по нажатию на которую текущий кадр из видео будет сохранён на ваш компьютер в формате JPEG.

mobile menu iconСколько это всё стоит?mobile menu icon

  • Нисколько. Наши сервисы абсолютно бесплатны для всех пользователей. Здесь нет PRO подписок, нет ограничений на количество или максимальную длину скачиваемого видео.