По завершении этого шага обучения на примере игры «Головоломка из лампочек с тегами» вы узнаете, как использовать Теги игрового процесса для поиска акторов, помеченных определённым тегом, прямо во время игры. Теги игрового процесса позволяют работать с несколькими устройствами без необходимости настраивать ссылки на них в редакторе. Такое решение открывает интересные игровые возможности, когда, к примеру, написанный вами код динамически изменяет, какие устройства активны, по мере продвижения игрока по игре.
Ниже пошагово описан процесс создания нового тега игрового процесса и его присвоения всем лампочкам головоломки на уровне:
- Откройте Проводник Verse и дважды щёлкните по файлу tagged_lights_puzzle.verse, чтобы открыть его в Visual Studio Code.
- В верхней части файла:
- Добавьте строку
using { /Verse.org/Simulation/Tags }, чтобы добавить ссылку на классtagи получить доступ к функцииGetCreativeObjectsWithTag(). - Добавьте строку
using { /Verse.org/Simulation }, чтобы получить возможность создавать редактируемые свойства.
using { /Fortnite.com/Devices } using { /Verse.org/Native } using { /UnrealEngine.com/Temporary/Diagnostics } using { /Verse.org/Simulation/Tags } using { /Verse.org/Simulation } log_tagged_lights_puzzle := class(log_channel){} - Добавьте строку
-
Перед классом
log_tagged_lights_puzzleдобавьте новый подкласс с названиемpuzzle_light, который будет наследоваться от классаtag. Название подкласса станет пользовательским тегом игрового процесса, который вы сможете использовать на любом устройстве творческого режима.# Наследуется от класса `tag` из модуля Verse.org/Simulation/Tags для создания нового тега игрового процесса. puzzle_light := class(tag){} log_tagged_lights_puzzle := class(log_channel){} - На панели инструментов UEFN нажмите на Создать сценарии Verse, чтобы скомпилировать код и новый тег игрового процесса
puzzle_lightдля проекта. - Чтобы открыть панель Сведения устройства, выберите Настраиваемое освещение в разделе Окно сборки в UEFN.
- На панели «Сведения»:
- Нажмите на Добавить новый компонент и выберите Разметка тегов Verse.
- Выберите компонент Разметка тегов Verse, чтобы отобразить его настройки на панели Сведения.
- В разделе Теги игрового процесса отредактируйте свойство Теги и добавьте тег
puzzle_light.

К одному устройству можно добавить сразу несколько тегов, поэтому каждое устройство может одновременно принадлежать к нескольким группам. Например, устройство с тегами
tag1иtag2будет найдено как при вызовеGetCreativeObjectsWithTag(tag1{}), так и при вызовеGetCreativeObjectsWithTag(tag2{}). - В определении класса
tagged_lights_puzzleдобавьте два массива переменных:- Редактируемый массив переменных типа
logicс именемLightsStateдля представления текущего состояния всех лампочек (включены/выключены). Он также используется для того, чтобы задать начальное состояние лампочек, поэтому количество его элементов должно соответствовать количеству лампочек с тегомpuzzle_light. В этом примере все лампочки по умолчанию не горят, поэтому начальное значение для них будетfalse.@editable var LightsState : []logic = array{false, false, false, false} - Редактируемый массив переменных
Lightsтипаcustomizable_light_deviceдля хранения всех устройств «Настраиваемое освещение» с тегом игрового процессаpuzzle_light.@editable var Lights : []customizable_light_device = array{}
- Редактируемый массив переменных типа
- Когда игра начинается, устройство должно настроить лампочки в соответствии с начальной конфигурацией, указанной в массиве
LightsState, а также сохранить ссылки в массивеLights, чтобы их можно было обновлять при изменении состояния игры. Эта задача будет выполняться в методеSetupPuzzleLights() : voidи вызываться в методеOnBegin()для подготовки лампочек в момент запуска игры.SetupPuzzleLights() : void = Logger.Print("Подготавливаю лампочки в игре") OnBegin<override>()<suspends> : void = SetupPuzzleLights() - В
SetupPuzzleLights()мы находим все устройства с тегомpuzzle_lightпутём вызоваGetCreativeObjectsWithTag(puzzle_light{})и сохранения их в массивTaggedActors. Так как массивTaggedActorsизменяться не будет, а его область видимости находится в пределахSetupPuzzleLights(), вам не нужно явно указывать тип массива, так как в данном контексте он определяется логически.SetupPuzzleLights() : void = Logger.Print("Подготавливаю лампочки в игре") TaggedActors := GetCreativeObjectsWithTag(puzzle_light{})Различные вызовы функции
GetCreativeObjectsWithTag()могут расположить устройства в получаемом массиве в разном порядке: всё потому, что нет определённого порядка при получении акторов с тегами игрового процесса. - После того, как мы собрали все устройства с тегом
puzzle_light, необходимо убедиться, что каждая лампочка соответствует начальному состоянию, указанному в массивеLightsState. Для этого мы можем воспользоваться цикломfor.for: ActorIndex -> TaggedActor : TaggedActors do: TaggedActor - Функция
GetCreativeObjectsWithTag()возвращает массив объектов типаcreative_object_interface. В этом примере нам будет необходимо взаимодействовать с каждым акторомTaggedActorкак с объектомcustomizable_light_deviceдля включения/выключения лампочки.- Вы можете преобразовать класс в один из его подклассов (это называется приведение типов), используя синтаксис
NewDeviceReference := device_type_to_cast_to[DeviceReference], гдеdevice_type_to_cast_to— это нужный вам тип устройства, в качестве которого в данном примере выступаетcustomizable_light_device. Здесь используется выражение с возможностью ошибкой, поскольку приведение типов может не выполниться, если устройство невозможно будет привести к данному типу (например если это устройство другого типа).LightDevice := customizable_light_device[TaggedActor]
Функция
GetCreativeObjectsWithTag()возвращает тип[]creative_object_interface: она может возвращать различные типы акторов, поэтому возвращаемый ей тип объекта — это интерфейс, который должен быть реализован во всех акторах, что и позволит возвращать соответствующий объект вGetCreativeObjectsWithTag(). Более подробно это описано в разделе, посвящённом тегам игрового процесса.- С конструкциями
forможно использовать выражения с возможной ошибкой в качестве фильтра и создавать новые переменные, которые затем можно будет использовать в блоке кодаfor. В этом случае к выражению итерации добавьте преобразование типа кcustomizable_light_deviceиз предыдущего шага.for: ActorIndex -> TaggedActor : TaggedActors LightDevice := customizable_light_device[TaggedActor] do: LightDevice - Последнее выражение в блоке кода — это результат блока кода. Выражение
forвозвращает результат блока кода для каждой итерации в массиве, поэтому результатом этого выражения сforбудет являться массив ссылок на объектыcustomize_light_deviceс тегомpuzzle_light. Это означает, что вы можете напрямую обновить массивLightsпри помощи результата выраженияfor.set Lights = for: ActorIndex -> TaggedActor : TaggedActors LightDevice := customizable_light_device[TaggedActor] do: LightDevice - В этом цикле
forдля лампочек также должны вызываться методыTurnOn()/TurnOff(), чтобы обеспечить соответствие их начальному состояниюLightsState, установленному в редакторе. Выражениеforможет возвращать индекс, используемый для получения текущего устройства с тегом (в нашем примере —ActorIndex), который вы можете использовать для обращения к массивуLightsState, чтобы узнать, должна ли лампочка быть включена или выключена.set Lights = for: ActorIndex -> TaggedActor : TaggedActors LightDevice := customizable_light_device[TaggedActor] ShouldLightBeOn:= LightsState[ActorIndex] do: LightDevice - Далее вызовите метод
TurnOn()/TurnOff()в зависимости от того, каким является значениеShouldLightBeOn(true/false). Вы можете использовать выражение сifдля выполнения различных выражений на основе условия (в частности, это относится к выражениям с возможной ошибкой). В этом случае для выражения с возможной ошибкой можно использовать оператор запроса?сIsLightOn, которое успешно выполнится, еслиShouldLightBeOnбудет возвращатьtrue(и будет вызван методTurnOn()), либо не выполнится, еслиShouldLightBeOnбудетfalse(и будет вызван методTurnOff()).set Lights = for: ActorIndex -> TaggedActor : TaggedActors LightDevice := customizable_light_device[TaggedActor] ShouldLightBeOn := LightsState[ActorIndex] do: if (ShouldLightBeOn?) then LightDevice.TurnOn() else LightDevice.TurnOff() LightDevice - Также будет полезно выводить на экран индекс лампочки и её начальное значение, чтобы убедиться, что код работает должным образом, а также сравнить с тем, что мы видим на уровне.
- При использовании фигурных скобок
{}в середине строки выражение между ними рассчитывается первым и его значение добавляется к строке. Таким образом, вы можете использовать выражениеifв середине строки для добавления значений при соблюдении условия.set Lights = for: ActorIndex -> TaggedActor : TaggedActors LightDevice := customizable_light_device[ActorIndex] ShouldLightBeOn := LightsState[ActorIndex] do: Logger.Print("Добавляю лампочку с индексом {ActorIndex} и состоянием:{if (ShouldLightBeOn?) then "Вкл." else "Выкл."}") if (ShouldLightBeOn?) then LightDevice.TurnOn() else LightDevice.TurnOff() LightDevice
- Вы можете преобразовать класс в один из его подклассов (это называется приведение типов), используя синтаксис
- Метод
SetupPuzzleLights()теперь должен выглядеть следующим образом:SetupPuzzleLights() : void = TaggedActors := GetCreativeObjectsWithTag(puzzle_light{}) <# Проверяем, относится ли каждое устройство с тегом puzzle_light к типу customizable_light_device путём приведения типов. Если это так, получаем его начальное состояние LightState, чтобы включить (TurnOn()) или выключить (TurnOff()) устройство LightDevice. Сохраняем все объекты customizable_light_device с тегом в массив Lights. #> set Lights = for: ActorIndex -> TaggedActor : TaggedActors LightDevice := customizable_light_device[TaggedActor] ShouldLightBeOn := LightsState[ActorIndex] do: Logger.Print("Добавляю лампочку с индексом {ActorIndex} и состоянием:{if (ShouldLightBeOn?) then "Вкл." else "Выкл."}") if (ShouldLightBeOn?) then LightDevice.TurnOn() else LightDevice.TurnOff() LightDevice - Сохраните сценарий в Visual Studio Code.
- На панели инструментов UEFN нажмите на Создать сценарии Verse, чтобы скомпилировать код.
- Нажмите Играть на панели инструментов UEFN, чтобы протестировать уровень.
Во время тестирования уровня вы должны увидеть, что каждая лампочка в массиве Lights выводится в журнале выходных данных вместе с её начальным состоянием.
Что дальше
Дальше вы узнаете, как переключать определённую комбинацию лампочек по нажатию кнопки игроком.