Как написать скрипты для игр

Для многих начинающих игростроевцев, которые уже собирают свою команду, чтобы слепить на коленке очередной шедевр, программирование часто видится жутким монстром, с которым непонятно как бороться. Вроде и в 3D уже рисовать умеют, и в Photoshop кисточкой сноровисто работают, и другие полезные программы неплохо знают… Но как только дело доходит до кода, начинается паника и неразбериха: “Кто спрограммирует? Кто напишет заветные строчки? А если и напишет, то как в них потом разобраться?!”.

Данный материал открывает серию статей, в которых мы на простых примерах научим вас читать с листа и писать несложный программный код. Суперкрутыми программистами вы, разумеется, не станете (для этого надо учиться значительно дольше), но иероглифы кода перестанут быть для вас чем-то непонятным, от чего нужно держаться подальше.

Сегодня мы расскажем вам, как создать игровой мутатор оружия, превращающий заурядную шестистволку UT2004 в смертоносный плазмаган “Мегакиллер”. Пример, с одной стороны, несложный: разберутся даже самые начинающие. С другой стороны — ощутимый результат будет достигнут уже по факту прочтения вами статьи (и отработки ее на практике). Вы сами напишете мутатор для UT и опробуете его в игре.

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

Установка среды разработки

В UT2004 встроен собственный компилятор UCC для игровых скриптов. Но, к сожалению, он является консольным приложением и компиляция в нем — весьма трудоемкий процесс. Поэтому компания Epic Games выпустила программный пакет Unreal Developer Environment (далее — UDE), который может заметно упростить процесс написания игровых скриптов и их компиляцию. UDE распространяется в виде ut4mod-файла, то есть инсталлируемого игрового модуля.

При запуске установки модуля никаких особых манипуляций совершать не нужно — модуль сам определит наличие игры на вашем винчестере (через реестр) и путь к ней. Просто кликните кнопку Next. После установки на рабочем столе появится ярлык для UDE.

Классы игры и иерархия

Вся логическая составляющая UT представляет собой совокупность классов объектов, которые объединены в строгую иерархическую схему — так называемое дерево наследования. О наследовании и объектно-ориентированном программировании читайте на отдельном текстовом блоке.

Распаковка игровых скриптов

Изначально uc-файлы, содержащие классы объектов, упакованы в u-файлы. Но для работы с UDE нам придется их распаковать. Для этого в папке UT2004System создаем bat-файл (или cmd) со следующим содержимым: @for /f «tokens=*» %%a in (‘dir /b *.u’) do ( ucc batchexport %%a class uc ..%%~naClasses ). Затем стартуем этот файл, и через 2—3 минуты все требуемые скрипты будут распакованы.

Запускаем UDE, появится окно мастера настройки среды разработки (в дальнейшем это конфигурирование можно повторить по команде File/Wizards/The UDE Setup Wizard внутри программы). Настроек несколько, и все их можно использовать со значениями по умолчанию. Также необходимо проверить, чтобы пункт Create Class/Package Trees (рис. 1.) был активным (он будет выведен на шаге 3 — Step 3: Class/Package Tree). Наконец, жмем Finish и ждем около минуты, пока среда разработки просканирует игровую папку на наличие файлов скриптов и объединит все найденные классы в дерево классов.

Настройка среды разработки

Перед нами среда разработки. Для организации рабочего пространства перемещаем открытые окна влево основного экрана с помощью соответствующей кнопки в правом верхнем углу каждого открытого окна. Теперь окна будут выезжать при наведении курсора на соответствующие значки панели слева. Для нас важны два окна: Classes (рис. 3.) и Packages (рис. 4.). В первом окне представлено иерархическое дерево всех игровых классов. Во втором — файлы скриптов в соответствии с их принадлежностью игровым архивам (u-файлам).

Двойной клик на любом пункте этих окон автоматически открывает соответствующий uc-файл/класс. Заголовок текстового окна с кодом вынесен влево, что весьма необычно, поэтому для закрытия окна нужно кликнуть на крестик в левом верхнем углу (а не в правом, как это обычно делается в Windows).

Кстати, неоценимой заслугой UDE является возможность проследить источник любых данных. Для этого достаточно навести курсор на соответствующую лексическую единицу (например, имя класса или функции) и кликнуть на ней, удерживая нажатой клавишу Ctrl. При этом будет открыт файл, где интересующая нас единица была объявлена, а само объявление будет подсвечено. С помощью этой несложной функции очень просто исследовать происхождение тех или иных переменных, функций, классов.

Принципы объектно-ориентированного программирования

В ООП существуют три основных принципа, на которых строятся практически все логические манипуляции с объектами.

Инкапсуляция — объединение внутри объекта данных с методами для их обработки. Например, если рассматривается класс “Лампочка”, то у него должны быть методы “включить свет” и “выключить свет”.

Наследование — создание класса объектов на основе уже существующего класса. При этом создаваемый класс будет не только содержать все данные и методы базового класса, но и обладать своими собственными. Методы базового класса могут быть переопределены. Примеры наследования и переопределения: если класс “Пегас” наследуется от класса “Лошадь”, то у первого появляется новое свойство — “крылья” и соответствующий метод “махать крыльями”. Все остальное у этих двух классов одинаковое. Если мы рассмотрим класс “Русалка”, основанный на классе “Человек”, то в данном случае будет иметь место переопределение свойства “ноги” на “рыбий хвост”, а метод “двигаться” будет вместо движения ног отвечать за перемещение хвоста.

Полиморфизм — что это такое, проще всего рассмотреть на конкретном примере. Рассмотрим два класса объектов — “Пегас” и “Лошадь”. Полиморфизм заключается в том, что мы можем рассматривать любого пегаса как лошадь и, например, у обоих объектов выполнять метод “кушать траву” или “бежать галопом”.

Многие начинающие программисты не различают понятия “класс” и “объект”. Но при этом эти два понятия различаются примерно так же, как и, скажем, чертеж устройства и готовое устройство в магазине. В жизни их спутать трудно.

Создание проекта

К сожалению, в UDE кнопка “Создать новый проект” отсутствует. Поэтому создаем в корневой папке UT2004 файл CreateNewClass.bat с командами:

set pkg=Megakiller

md %pkg%

md %pkg%Classes

echo class %pkg% extends //base class>> %pkg%Classes%pkg%.uc

Значение переменной pkg — это имя нашего проекта (в данном случае — Megakiller). Остальные строки генерируют “пустой” скрипт.

После запуска пакетного файла в среде разработки выполняем команду UT2004 / Refresh Package/Class Tree. Теперь в списке архивов появился новый пункт Megakiller, а в нем скрипт Megakiller.uc. Этап подготовки завершен, переходим к программированию.

Идея модификации

Идея мутатора заключается в следующем: когда игрок стреляет в альтернативном режиме из “Мегакиллера”, стволы вместо пуль выпускают энергетические лучи, как у шокового ружья. При соприкосновении луча с любым препятствием происходит взрыв плазмы, который наносит здоровью противника заметный урон. При последовательном попадании нескольких лучей в одного и того же противника враг начинает гореть, а та часть тела, куда попал заряд, ампутируется.

Перед изучением нижеследующей информации настоятельно рекомендуется изучить текстовый блок “Анатомия Unreal-класса”.

Внимание! Читая нижеследующие абзацы, смотрите соответствующие строки в листинге кода, приведенном на отдельной странице (номера строк указаны слева от кода).

Класс оружия

Наше оружие будет объектом нового игрового класса Megakiller, основанном на уже существующем классе Minigun (строка 1). “Мегакиллер” переопределяет некоторые свойства (строка 2) родительского класса (строки 2-7): альтернативную стрельбу (FireModeClass), событие при получении оружия (PickupClass), а также описание оружия (Description). Стоит заметить, что основным режимом стрельбы является FireModeClass(0), а альтернативным — FireModeClass(1).

35 Kb

Рис. 1. Диалог создания дерева классов и архивов.

Класс альтернативной стрельбы

Класс альтернативной стрельбы для “Мегакиллера” представляет собой переработанный базовый класс MinigunAltFire. Для создания этого класса кликаем правой кнопкой мыши на нашем проекте Megakiller в окне Packages и в контекстном меню выбираем Create Sub Class. В открывшемся диалоговом окне (рис. 3.) в поле Parent Class вводим имя базового класса (MinigunAltFire), а в New Class Name —имя нашего нового класса (MegakillerAltFire). Обязательно ставим галочку в самом низу окна и жмем Оk. После этого в нашем проекте появляется новый файл MegakillerAltFire.uc.

27 Kb

Рис. 2. Окна с деревом классов и списком архивов.

В начале файла объявляем несколько новых свойств для объектов класса (строки 2-5): визуальный тип взрыва (ExplosionClass), визуальный тип следа от взрыва, например на стенах (ExplosionDecalClass). Тип луча при альтернативной стрельбе (BeamEffectClass) и радиус поражения при взрыве (DamageRadius).

Методы должны объявляться в порядке, обратном порядку обращения к ним. То есть если метод X вызывает метод Y, то Y должен быть объявлен перед X. С учетом этого добавляем два новых метода Explode и BlowUp и переопределяем имеющийся SpawnBeamEffect. О последнем стоит упомянуть отдельно. Дело в том, что все оружие делится на две категории: оружие непосредственного поражения (пули, лучи) и оружие, поражающее посредством снарядов (ракет, осколков). В первом случае противник, на которого нацелено оружие, получает повреждение моментально, во втором случае решение о повреждении принимается после взрыва снаряда с учетом множества факторов (например, попал ли противник в радиус поражения). Рассмотрим эти методы детально.

Метод SpawnBeamEffect (строки 23-30) имеет стандартный интерфейс, обеспечивающий успешный расчет попадания. Объявляем локальную переменную ShockBeamEffect (ключевое слово «local»), значение которой задаем с помощью специальной функции Spawn с аргументами: какой эффект луча мы хотим получить, в каком направлении и откуда луч испускается. Наконец, в точке соприкосновения луча устраиваем взрыв, вызвав метод Explode.

В методе Explode (строки 11-22) используется объект Instigator для уточнения, кто именно осуществил выстрел. После проверки, что взрыв возможен (луч не ушел в небо, например), воспроизводится звук взрыва и создаются спрайтовые визуальные эффекты для имитации взрывной волны и следа от взрыва на стенах. Затем проверяется, попадает ли игрок в зону поражения (строка 19). Если попадает, ему наносится повреждение в размере DamageMin (строка 41).

Для вычисления расстояния от игрока до центра взрыва используется функция VSize (длина вектора). В конце вызывается метод физического взрыва для противников — BlowUp (строки 6-10). Этот метод задействует всего две функции объекта Instigator — HurtRadius и MakeNoise. Первая функция создает сферу поражения требуемых силы и радиуса в нужной точке пространства, вторая — информирует ИИ игры о том, что мы только что пошумели.

Свойства, задаваемые в соответствующем блоке (строки 31-43): спецэффекты взрыва (ExplosionClass) и следы от него (ExplosionDecalClass), тип луча (BeamEffectClass), огонь из ствола при выстреле (FlashEmitterClass), радиус (DamageRadius) и некоторые параметры поражения при взрыве (DamageMin, DamageMax, bSplashDamage и bRecommendedSplashDamage). Плюс тип повреждений при взрыве (DamageType).

18 Kb

Рис. 3. Диалог создания подкласса.

Классы повреждения

По уже известной нам схеме добавляем еще два игровых класса. Класс наносимых оружием повреждений при взрыве MegaBeamDamage наследуется от базового класса DamTypeShockCombo. В новом классе переопределяются значения параметров: горит ли тело убитого врага(bFlaming), наносится ли урон дружественным игрокам (bSuperWeapon), наносятся ли повреждения при прямом попадании мгновенно (bInstantHit) и предохраняет ли броня от травм (bArmorStops).

Класс MegakillerPickup базируется на MinigunPickup и служит для одной цели: как только игроку в руки попадает “Мегакиллер”, ему выдается уведомление об этом, что проиллюстрировано в строках 4-5 листинга 4.

35 Kb

Рис. 4. Окно компиляции.

Класс игрового мутатора

Игровой класс MegakillerWeaponMod создаем на основе стандартного класса модов Mutator с параметром config(user). В классе переопределяется одна-единственная функция — CheckReplacement (строки 2-33), задача которой состоит в подмене всех имеющихся экземпляров минигана “Мегакиллерами”. А располагаться оружие может в одном из трех мест:

— в специальных точках карты (строка 7). Объект класса xWeaponBase позволяет узнать тип оружия с помощью обращения к полю WeaponType и при необходимости произвести замену (строка 11).

— просто лежать на карте (строка 15). Тут нам помогает класс WeaponPickup (строка 15). Подмена осуществляется функцией ReplaceWith (строка 19).

— оружие, которое есть у игрока в боекомплекте. Используемый класс объекта WeaponLocker дает возможность в цикле (строка 26) по очереди перебрать все имеющиеся единицы оружия и заменить “миниган”, если таковой имеется (строки 28-29).

В конце кода задаются значения параметров мутатора (строки 34-40): тип оружия по умолчанию (DefaultWeapon) и описания мутатора (GroupName, FriendlyName, Description).

13 Kb

Рис. 5. Сообщение об ошибке и справка.

Исходный код модификатора
35 Kb 27 Kb

Дуэли на «Мегакиллерах» иногда превращают обычный бой в феерическое зрелище.

Чернокожий стрелок пытается безуспешно подстрелить «античную» мадам.

25 Kb 39 Kb

Местные леди способны просто-таки заряжать вас энергией!

Каждый Чебурашка мечтает о большой пушке!

Компиляция и тестирование

Когда все скрипты готовы, остается только откомпилировать проект командой UT2004/Quick Compile Active Document (должен быть открыт любой скрипт проекта). Появится сообщение, что проект Megakiller не прописан внутри файла UT2004.ini (а это необходимо для компиляции). Поэтому кликаем Yes, а затем в следующем окне Ok.

Если все нормально, то через 10—20 секунд проект будет откомпилирован (редактор UnrealEd не должен быть запущен), а кнопка Ok в левом нижнем углу окна компиляции станет активной (рис. 4.). Если же надпись сменилась на Error, значит, во время компиляции произошла ошибка. Если кликнуть на этой кнопке, внизу экрана на вкладке Compile Results будет выведено, что именно вызвало ошибку, а в правом нижнем углу окна UDE появится небольшая справка о возможных способах устранения ошибки (Рис. 5).

Если все прошло успешно, то запускаем игру, выбираем Instant Action в меню, ставим режим Deathmatch и на вкладке мутаторов добавляем мутатор Megakiller, после чего кликаем Play. Когда мод протестирован в деле, его можно выложить, например, в интернет. Дистрибутивными файлами являются Megakiller.u и Megakiller.ucl (автоматически генерируется при компиляции) из папки UT2004System.

Для того чтобы вы сразу могли оценить действие мутатора и поиграть в него, мы выкладываем полную версию “Мегакиллера” на наш диск.

Анатомия Unreal-класса

Класс игры имеет унифицированную архитектуру. Структура файла следующая.

 — Заголовок, содержащий объявление класса:

class ClassName extends BaseClass config(user); где ClassName — название нашего класса, BaseClass — базовый класс, на основе которого создается новый класс, config(user) — пример параметра в объявлении класса — указывает, что используются конфигурационные параметры из файла User.ini. Все игровые классы имеют в качестве родительского класс Object или любой из его классов-потомков. Лексемы class и extends являются зарезервированными обязательными атрибутами объявления игрового класса. Важно запомнить, что корректным является только тот uc-файл, имя которого совпадает с названием объявленного в нем класса. И в одном uc-файле должен быть описан только один класс.

 — Объявления новых переменных (свойств класса) в следующем формате:

var() class<PropertyClass> PropertyName; или var() SimpleType PropertyName; где PropertyClass — название класса создаваемого свойства, SimpleType — элементарный тип, такой как byte (байтовое значение от 0 до 255), int (знаковый целый тип), bool (логический тип), float (знаковый вещественный тип), string (символьная строка) и т.д. (полный список элементарных типов можно посмотреть в справке UDE), PropertyName — имя нового свойства.

— Объявления новых методов или переопределение унаследованных от базового класса имеют следующий вид:

simulated function FunctionName( VariableType VariableName, … ) { … } где FunctionName — имя нового метода (или переопределяемого), содержимое круглых скобок — аргументы метода — может отсутствовать, состоять из одного или нескольких значений. В этом случае VariableType  — тип (класс) аргумента, VariableName — имя аргумента. Обратите внимание, что в случае переопределения метода родительского класса, заголовок (интерфейс) метода (строка, стоящая перед фигурными скобками) не должен модифицироваться! Лексема simulated — один из возможных параметров метода — говорит о том, что метод будет выполняться только на клиентской машине. Фигурные скобки обособляют в коде тело метода.

 — Задание параметров (свойств) по умолчанию класса:

defaultproperties { Variable1Name=Class’Package.ClassName’; Variable2Name=Variable2Value; … } где defaultproperties  — лексема, указывающая начало блока свойств, Variable1Name — название свойства, представляющего собой некоторый другой объект класса ClassName, содержащегося в u-файле с именем Package. Параметр Variable2Name имеет элементарный тип, поэтому и присваиваемое значение Variable2Value должно иметь тот же тип. Символ «=» означает операцию присвоения значения справа переменной слева. Фигурные скобки обособляют в коде блок присвоений.

* * *

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

Создание скриптов — неотъемлемая часть даже самых простых игр. Эти небольшие наборы кода работают вместе, чтобы делать самые разные вещи.

Версия: C# 7.3, Unity 2019.2, Unity

Создание скриптов — неотъемлемая часть даже самых простых игр. Эти небольшие наборы кода работают вместе, чтобы делать самые разные вещи: от перемещения персонажа по экрану до отслеживания инвентаря. Разработчики игр пишут скрипты в Unity на C#, мощном объектно-ориентированном языке программирования, разработанном Microsoft около 2000 года. С тех пор он стал одним из самых популярных языков программирования. Команда Unity выбрала C# в качестве основного языка программирования Unity, поскольку он хорошо документирован, прост в освоении и гибок.

В основе Unity лежит хорошо документированный API, с которым могут взаимодействовать скрипты. В этом уроке вы создадите простую игру — начав с нескольких моделей и изучив, как использовать наиболее важные части Unity API. Вы узнаете, как создавать скрипты C#, которые:

  • Создают переменные, которые можно изменить в редакторе.
  • Обнаруживают ввод игрока и реагируют на него.
  • Используют физику для создания взаимодействий.
  • Изменяют значения с течением времени несколькими способами.

Перед началом убедитесь, что вы соответствуете следующим требованиям:

  • На вашем компьютере установлена последняя стабильная версия Unity.
  • На вашем компьютере установлена среда разработки скриптов, поддерживающая C#. Я рекомендую Visual Studio Community для Windows и Visual Studio Code для macOS и Linux.
  • Вы знаете основы C#. Если вы новичок в программировании, сначала ознакомьтесь с видеокурсом Brian’s Beginning Programming with C#. Если вы хотите сразу же погрузиться в C#, возьмите копию (или загрузите бесплатную версию в формате PDF) Желтой книги по программированию на C#, так я научился использовать C#.

Итак, вы готовы открыть для себя Unity API, создав простую игру!

Приступая к работе

Скачайте материалы для проекта с помощью кнопки «Скачать материалы урока» вверху страницы, распакуйте их куда-нибудь и откройте стартовый проект в Unity.

Для начала обратите внимание на окно Project и разверните папку RW. Этот проект поставляется с набором готовых ассетов, которые вы будете использовать, чтобы вдохнуть жизнь в игру с помощью скриптов:

Набор ассетов в окне Project редактора Unity

Чтобы сосредоточиться на написании скриптов, вот включенные папки ресурсов и их содержимое:

  • Materials: Единый материал, используемый всеми моделями для оптимальной работы.
  • Models: Некоторые модели варьируются от небольших дымовых облаков до больших наземных моделей.
  • Music: Фоновая музыка для игры. Песня — Flying Kerfuffle Кевина Маклэода.
  • Prefabs: Набор готовых префабов, чтобы упростить внесение изменений в игровых объектов, уже присутствующих в сценах.
  • Scenes: Сцены Game и Title.
  • Scripts: Пусто! Здесь вы разместите скрипты, которые будете создавать.
  • Sounds: Несколько 8-битных звуковых эффектов, созданных с помощью bfxr.
  • Sprites: Здесь есть одна таблица спрайтов для некоторых небольших элементов пользовательского интерфейса.
  • Textures: Одна текстура, которая используется в общем материале.

Теперь откройте сцену Game в папке RW / Scenes, если она еще не открыта, и посмотрите вокруг в режиме просмотра Scene.

Просмотр сцены проекта в окне Scene редактора Unity

Есть несколько плавучих островов с ветряными мельницами, мостами и небольшой железнодорожной веткой, на которой стоит синяя сенокосилка. Теперь взглянем на Иерархию:

Игровые объекты в окне Hierarchy редактора Unity

Вот краткий обзор игровых объектов:

  • Music: источник звука, воспроизводящий счастливую мелодию в цикле.
  • Main Camera: камера, которая направлена вниз на сцену, чтобы обеспечить хороший обзор.
  • Directional Light: единственный источник света, имитирующий солнце.
  • Scenery: этот игровой объект удерживает землю и ветряные мельницы.
  • Hay Machine: это синяя машина, сидящая на рельсах, которая состоит из нескольких игровых объектов, чтобы ее можно было легко настроить в дальнейшем.

Затем нажмите кнопку воспроизведения в верхней части редактора и посмотрите на представление Game, чтобы увидеть, что происходит.

Проект игры в окне Game редактора Unity

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

Нажмите кнопку play еще раз, чтобы остановить тестирование «игры».

Теперь, когда вы знакомы с проектом, пора приступить к написанию скриптов!

Ваш первый скрипт

Создавать новые скрипты в Unity довольно просто. Щелкните правой кнопкой мыши папку RW / Scripts, выберите Create > C# Script и назовите скрипт Rotate.

Создание скрипта в Unity

Теперь Unity создает и немедленно компилирует голый скрипт MonoBehaviour.

Хотя скрипт еще ничего не делает, вы уже можете использовать его как компонент, прикрепив его к игровому объекту. В этом случае скрипт Rotate будет вращать колеса всех ветряных мельниц.

Компоненты — это экземпляры скриптов, что означает, что вы можете добавить столько компонентов к любому игровому объекту, сколько захотите. Любые изменения, внесенные в скрипт, отразятся на всех его компонентах.

Разверните Scenery в Иерархии, чтобы раскрыть его потомков. Откройте Windmill в редакторе префабов, щелкнув стрелку рядом с его названием.

Кнопка для переход в редактирование префаба в окне Hierarchy редактора Unity

Примечание. Редактор Unity недавно обновил систему префабов. Чтобы получить более подробное представление о новой системе, ознакомьтесь с этим замечательным руководством!

Выберите Wheel, это потомок Windmill. Теперь нажмите кнопку Add Component в нижней части Инспектора, начните вводить «rotate», пока в списке не появится компонент Rotate, и выберите его.

Добавление компонента Rotate игровому объекту в Unity

Это добавит компонент Rotate к колесам всех ветряных мельниц.

Чтобы отредактировать скрипт, вам нужно открыть его в редакторе кода, таком как Visual Studio. Есть несколько способов открыть скрипт, но самый простой — найти исходный файл в окне Project и дважды нажать на него. Двойной щелчок по полю Script любого компонента также работает:

Расположение файла скрипта Rotate в окне Project редактора Unity

Используйте любой из описанных выше методов, чтобы открыть скрипт Rotate в редакторе кода по умолчанию. Вот как это выглядит в Visual Studio:

Код скрипта в редакторе Visual Studio

Сам скрипт представляет собой единый класс, производный от MonoBehaviour, базового класса Unity, от которого должны быть унаследованы все скрипты, если их нужно использовать в качестве компонентов.

MonoBehaviour является частью пространства имен UnityEngine и реализует несколько общедоступных методов, но, что более важно, огромный список функций событий.

Примечание. Функции — это другое название методов, все они являются подпрограммами. В языках ООП, таких как C#, вам следует использовать термин «метод», но Unity предпочитает вместо этого использовать функцию при описании большинства своих встроенных методов.

Unity по умолчанию добавляет методы Start и Update во все новые скрипты. На самом деле это функции событий, они вызываются, когда их запускает определенное действие. Вот несколько наиболее распространенных функций обработки событий, и когда они вызываются:

  • Start: при первой инициализации компонента.
  • Update: каждый кадр.
  • OnEnable: когда компонент включен (повторно).
  • OnDestroy: когда компонент уничтожен.

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

Добавьте следующую строку внутри метода Update:

transform.Rotate(0, 50 * Time.deltaTime , 0);

Эта строчка кода, которая постоянно создает вращение по оси Y с течением времени, уже демонстрирует некоторые возможности Unity API:

  • transform является унаследованным свойством MonoBehaviour и возвращает Transform игрового объекта, к которому прикреплен компонент. Класс Transform позволяет вам читать и изменять положение, поворот и масштаб игрового объекта.
  • Rotate — один из общедоступных методов класса Transform, одна из его сигнатур используется здесь для передачи поворота в градусах по осям X, Y и Z соответственно.
  • По оси Y передается значение 50 * Time.deltaTime. Time.deltaTime является частью пространства имен UnityEngine и возвращает время в секундах между последним и текущим кадром. Это значение может меняться со временем независимо от частоты кадров. По сути, это предотвращает замедление движения на медленных машинах и гиперрежим на более быстрых. Умножение значения Time.deltaTime на 50 означает, что вы хотите, чтобы значение увеличивалось на 50 в секунду. В данном случае это поворот на 50 градусов по оси Y в течение секунды.

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

Примечание. Редактор Unity использует углы Эйлера для изменения поворота игрового объекта — это знакомые оси X, Y и Z. На самом деле движок Unity внутренне использует кватернионы, которые состоят из значений X, Y, Z и W. Эти значения очень сложно интерпретировать, и они не предназначены для прямого использования. Чтобы узнать больше о различиях, взгляните на документацию Unity по этому вопросу.

Сохраните этот скрипт и вернитесь в редактор.

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

Значок обновления скрипта в редакторе Unity

Если вы еще не вышли из режима редактирования префаба, сделайте это сейчас, щелкнув стрелку влево рядом с префабом Windmill в Иерархии. Вам будет предложено сохранить или отменить изменения. Нажмите на кнопку Save.

Окно предложением сохранить префаб в редакторе Unity

Теперь запустите воспроизведение сцены. Вы заметите, что колеса ветряной мельницы теперь медленно вращаются, так расслабляюще.

Игровой объект мельница вращается в Unity

Теперь предположим, что вы хотите настроить скорость вращения колес или добавить компонент Rotate к другому игровому объекту, который должен вращаться по другой оси. Было бы неплохо, если бы вы могли изменить эти значения в редакторе?

Вот тут-то и пригодятся переменные!

Переменные

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

Откройте скрипт Rotate в вашем любимом редакторе кода и добавьте следующую строку прямо над методом Start:

public Vector3 rotationSpeed;

Эта переменная изменит скорость и по какой оси будет происходить вращение.

Модификатор public в контексте Unity означает, что эта переменная будет доступна редактору и другим классам.

Vector3 — это структура, в которой хранятся значения X, Y и Z, Vector3 может использоваться для передачи положения, поворота или масштаба игрового объекта.

Теперь замените эту строку:

transform.Rotate(0, 50 * Time.deltaTime , 0);

Следующим кодом:

transform.Rotate(rotationSpeed * Time.deltaTime);

Скорость вращения теперь передается в метод Rotate с помощью переменной, что упрощает ее изменение. Векторы можно умножать на типы переменных с одним значением, такие как deltaTime, для одновременного изменения всех включенных значений вектора. Например, Vector3 со значением (X: 1, Y: 2, Z: 3), умноженное на float со значением 3, приведет к Vector3 со значением (X: 3, Y: 6, Z : 9).

Всегда выбирайте переменную вместо «магического числа», такого как 50, которые вы добавили ранее. Это позволит вам изменять и повторно использовать значения, не открывая скрипт.

Теперь сохраните скрипт и вернитесь в редактор. Откройте префаб Windmill из Иерархии, как вы делали раньше, и снова выберите игровой объект Wheel.

Взгляните на Inspector, компонент Rotate теперь имеет поле, которое вы можете настроить:

Параметры компонента Rotate в окне Inspector редактора Unity

Измените значение Y в поле Rotation Speed на 120 и выйдите из режима префаба, нажав на стрелку в верхнем левом углу Иерархии, и сохранив изменения при появлении запроса.

Выход из режима редактирования префаба в Unity

Теперь поиграйте в сцену. Колеса вращаются, как и раньше, но чуть быстрее.

Огромным преимуществом наличия переменных в редакторе является то, что вы можете изменять их в режиме воспроизведения! Выберите колесо одной из ветряных мельниц в окне Hierarchy и попробуйте изменить параметр скорости вращения Rotation Speed. Вы можете перемещать значение Y слева направо или изменять число напрямую.

Настройка параметров компонента Rotate в окне Inspector редактора Unity

Это приведет к тому, что колесо изменит свою скорость в реальном времени:

Игровой объект мельница изменяет скорость вращения в зависимости от параметров в окне Inspector редактора Unity

После выхода из режима игры все значения, которые вы установили для игровых объектов в Иерархии, будут сброшены. Это отличный способ поиграть со значениями и посмотреть, что работает лучше всего. Вы можете настроить высоту прыжка персонажа, количество здоровья вражеских орков или даже расположение элементов пользовательского интерфейса.

Конечно, как только вы найдете нужные значения, вы можете сохранить их, чтобы они применялись каждый раз при запуске игры. Самый надежный способ сделать это — скопировать и вставить значения в компоненты и использовать префабы.

Находясь в режиме игры, измените вращение одного из колес на все, что, по вашему мнению, выглядит хорошо, например, на 150 по оси Y. Теперь щелкните правой кнопкой мыши компонент Rotate вокруг его имени в Инспекторе или щелкните левой кнопкой мыши шестеренку параметров в правом верхнем углу компонента и выберите Copy Component. Это скопирует компонент и его значения в буфер обмена.

Копирование компонента и его значений в Unity

Далее остановите режим воспроизведения. Вы заметите, что скорость возвращается к своему прежнему значению в Inspector. Щелкните правой кнопкой мыши имя компонента Rotate и выберите Paste Component Values. Все значения, которые вы скопировали, теперь вставляются в компонент Rotate.

Вставка значений компонента в окне Inspector редактора Unity

Хотя это изменило скорость вращения одной из ветряных мельниц, вы хотите применить такое значение ко всем. Для этого выберите ветряную мельницу, которую вы изменили, и выберите Overrides > Apply All в правом верхнем углу Inspector, чтобы применить все изменения к префабу Windmill.

Применение изменений ко всем игровым объектам префаба в Unity

Далее идет опрос ввода от игрока, чтобы заставить машину двигаться и стрелять!

Ввод игрока и создание экземпляров префабов

Игра не была бы игрой, если бы не требовалось определенного уровня участия игрока. Скрипты могут получать состояние клавиатуры, мыши и любых подключенных геймпадов. Первая цель — заставить эту маленькую машинку двигаться по рельсам слева направо.

Движение

Создайте новый скрипт C# в RW / Scripts, назовите его HayMachine и откройте его в редакторе кода.

Добавьте следующие переменные прямо над Start:

public float movementSpeed;

Эта переменная позволит вам указать скорость, с которой может двигаться машина.

Теперь добавьте этот метод ниже Update:

private void UpdateMovement()
{
    float horizontalInput = Input.GetAxisRaw("Horizontal"); // 1

    if (horizontalInput < 0) // 2
    {
        transform.Translate(transform.right * -movementSpeed * Time.deltaTime);
    }
    else if (horizontalInput > 0) // 3
    {
        transform.Translate(transform.right * movementSpeed * Time.deltaTime);
    }
}

Этот фрагмент кода перемещает сеноуборочную машину, используя горизонтальный ввод игрока:

  1. Получить необработанный ввод горизонтальной оси с помощью класса Input и сохранить его в horizontalInput. Класс Input содержит все методы для опроса устройств ввода. GetAxisRaw возвращает текущее значение ввода, как определено в диспетчере ввода для горизонтальной оси:
    Окно диспетчера опроса данных с устройств ввода в Unity
    В этом случае вы можете использовать клавиши со стрелками влево и вправо, клавиши A и D или левый аналоговый джойстик в качестве входа.
  2. Если horizontalInput меньше 0, это означает, что было обнаружено движение влево по оси X. В этом случае использовать translate (то есть переместить) машину влево со значением движения movementSpeed в секунду.
  3. Если вместо этого horizontalInput больше 0, переместить машину вправо.

Когда Unity не обнаруживает никаких вводных данных, horizontalInput останется на 0 и машина не будет двигаться.

Теперь, чтобы вызвать метод, который вы добавили для каждого кадра, добавьте к нему вызов в Update:

UpdateMovement();

Затем сохраните этот скрипт и вернитесь в редактор. Выберите Hay Machine в Иерархии и добавьте к нему компонент Hay Machine.

Добавление компонента в окне Inspector редактора Unity

Установите Movement Speed на 14 и воспроизведите сцену. Используйте клавиши со стрелками или A и D для перемещения машины слева направо. Все работает!

Перемещение игрового объекта при помощи кнопок в Unity

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

Снова откройте скрипт HayMachine и добавьте следующую переменную под другими:

public float horizontalBoundary = 22;

Эта переменная будет использоваться для ограничения движения по оси X. В качестве значения по умолчанию присваивается 22, это будет начальное значение, которое также будет заполнено в редакторе.

Теперь отредактируйте оператор if-else в UpdateMovement, чтобы он использовал границу в своих проверках:

if (horizontalInput < 0 && transform.position.x > -horizontalBoundary) // 1
{
    transform.Translate(transform.right * -movementSpeed * Time.deltaTime);
}
else if (horizontalInput > 0 && transform.position.x < horizontalBoundary) // 2
{
    transform.Translate(transform.right * movementSpeed * Time.deltaTime);
}

Вот что изменилось:

  1. Мало того, что горизонтальный ввод должен быть отрицательным, прежде чем разрешить движение влево, положение машины по оси X также должно быть выше, чем отрицательное значение horizontalBoundary.
  2. Чтобы переместиться вправо, горизонтальный ввод должен быть положительным, а положение X машины должно быть ниже horizontalBoundary.

Изображение ниже более наглядно иллюстрирует происходящее:

Схема обозначения границ движения игрового объекта в Unity

Белые линии слева и справа обозначают границы, линия, проходящая через машину, является ее центром. Перемещение машины в любом направлении «блокирует» ее при достижении границы:

Движение игрового объекта в пределах границ в Unity

Сохраните скрипт и вернитесь в редактор. Попробуйте воспроизвести сцену и еще раз переместить машину влево и вправо. Машина останавливается, как только она перемещается к одному из краев.

Далее вы будете реализовывать скрипт стрельбы тюками сена!

Создание и стрельба снарядами

Прежде чем вы сможете начать что-либо запускать, вам нужно создать игровой объект для сена. Начните с создания нового пустого игрового объекта в окне Hierarchy, нажав правой кнопкой мыши на пустое пространство и выбрав Create Empty. Это создаст пустой игровой объект с именем GameObject в корне Иерархии.

Не снимая выделения с пустого GameObject, измените его имя на Hay Bale в Инспекторе и сбросьте его компонент Transform, щелкнув правой кнопкой мыши на компонент Transform и выбрав Reset.

Переименовывание игрового объекта в окне Inspector редактора Unity

Теперь добавьте 3D-модель в Hay Bale, перетащив модель Hay Bale из RW / Models на Hay Bale в Иерархии. Не снимая выделения с модели Hay Bale, назовите ее Hay Bale Model и сбросьте ее компонент Tranform. Теперь вы заметите сено, твердо стоящее на поверхности, как в режиме сцены, так и в режиме игры.

Игровой объект сено, которое находится на поверхности в сцене редактора Unity

Затем выберите Hay Bale и добавьте следующие компоненты с помощью кнопки Add Component:

  • Box Collider
  • Rigidbody
  • Rotate

Добавление компонентов игровому объекту в окне Inspector редактора Unity

Теперь, когда сено имеет необходимые компоненты для использования физики и может вращаться для анимации, пришло время настроить его.

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

Для начала установите флажок Is Trigger на Box Collider, чтобы тюк не мог толкать твердые тела. Затем установите флажок Is Kinematic на его Rigidbody, чтобы сено не провалилось сквозь поверхность. Наконец, установите Rotation Speed при вращении на (X: 300, Y: 50, Z: 0).

Сохраните сцену и нажмите кнопку воспроизведения. Вы заметите, что сено крутится на месте.

Игровой объект сено вращается в сцене редактора Unity

Чтобы сено двинулось вперед, вам нужно написать еще один служебный скрипт. Создайте новый скрипт C# в RW / Scripts, назовите его Move и откройте его в редакторе кода.

Добавьте следующие объявления переменных в начало класса прямо над методом Start:

public Vector3 movementSpeed; //1
public Space space; //2

Вот для чего они нужны:

  1. Присоединенный игровой объект будет двигаться со скоростью в метрах в секунду по осям X, Y и Z.
  2. Пространство, в котором будет происходить движение: World или Self. Пространство World трансформирует игровой объект в мировом пространстве Unity, игнорируя вращение игрового объекта, в то время как Self учитывает вращение игрового объекта в своих вычислениях.

Теперь добавьте в Update следующее:

transform.Translate(movementSpeed * Time.deltaTime, space);

Это то, что на самом деле перемещает игровой объект с помощью translation, это геометрический термин, который означает преобразование точки на расстояние в заданном направлении. По сути, это означает перемещение игрового объекта в контексте Unity.

Метод Translate принимает два параметра: первый — это направление и скорость, а второй — пространство, в котором происходит движение. Движение умножается на Time.deltaTime, чтобы обеспечить плавное движение в течение определенного периода времени.

Сохраните этот скрипт и вернитесь в редактор. Добавьте компонент Move в Hay Bale, установите для него Movement Speed на (X: 0, Y: 0, Z: 20) и оставьте Space равным World.

Настройка параметров компонента Move игрового объекта в в окне Inspector редактора Unity

Теперь запустите воспроизведение сцены, и вы увидите, как тюк сена летит к мостам и исчезает с экрана, отлично!

Игровой объект сено движется в сцене редактора Unity

Перетащите Hay Bale в папку RW / Prefabs, чтобы превратить его в префаб, и удалите оригинал из иерархии. Теперь вы сможете ссылаться на этот префаб, чтобы создавать больше игровых объектов типа Hay Bale, когда захотите.

Чтобы сеноуборочная машина выбрасывала тюки, вам нужно написать скрипт. Откройте скрипт HayMachine и добавьте следующие объявления переменных прямо над Start:

public GameObject hayBalePrefab; // 1
public Transform haySpawnpoint; // 2
public float shootInterval; // 3
private float shootTimer; // 4

Вот краткое объяснение переменных:

  1. Ссылка на префаб Hay Bale.
  2. Точка, с которой будет стрелять сено.
  3. Наименьшее время между выстрелами. Это не дает игроку спамить кнопку стрельбы и заполнить экран тюками сена.
  4. Таймер, который постоянно уменьшается, чтобы отслеживать, может ли машина стрелять или нет.

Теперь добавьте метод ShootHay под UpdateMovement:

private void ShootHay()
{
    Instantiate(hayBalePrefab, haySpawnpoint.position, Quaternion.identity);
}

Метод Instantiate создает экземпляр заданного префаба или игрового объекта и помещает его в сцену. Он принимает три параметра: префаб или игровой объект, позицию и поворот. В этом случае ссылка на префаб Hay Bale используется для создания экземпляра с его начальной позицией, такой же, как у haySpawnpoint Transform. Quaternion.identity используется для поворота, это значение поворота по умолчанию и похоже на Vector3.Zero, поскольку оно устанавливает поворот на (X: 0, Y: 0, Z: 0).

Чтобы вызвать приведенный выше код, вам понадобится код для запроса ввода. Добавьте следующий метод чуть выше ShootHay:

private void UpdateShooting()
{
    shootTimer -= Time.deltaTime; // 1

    if (shootTimer <= 0 && Input.GetKey(KeyCode.Space)) // 2
    {
        shootTimer = shootInterval; // 3
        ShootHay(); // 4
    }
}

Вот что делает этот блок кода:

  1. Вычитает время между предыдущим кадром и текущим из shotTimer, это будет уменьшать его значение на 1 каждую секунду.
  2. Если значение shotTimer равно или меньше 0, и клавиша пробела нажата …
  3. Сбросить таймер стрельбы.
  4. Стрелять в тюк сена!

И наконец, добавьте эту строку в Update, прямо под UpdateMovement () ;:

UpdateShooting();

Это вызывает метод над каждым кадром.

Теперь сохраните скрипт и вернитесь в редактор. Выберите Hay Machine в Иерархии, разверните его, щелкнув стрелку слева, и посмотрите на окно Inspector.

Параметры компонента скрипта игрового объекта в окне Inspector редактора Unity

Новые общедоступные переменные, которые вы только что добавили, стали полями, которые можно назначать. Перетащите Hay Bale из RW Prefabs в слот Hay Bale Prefab, перетащите дочерний игровой объект Hay Spawnpoint, который находится в Hay Machine, в слот Hay Spawnpoint и установите интервал стрельбы на 0,8.

Настройка параметров компонента скрипта игрового объекта в окне Inspector редактора Unity

Теперь сохраните сцену и нажмите кнопку воспроизведения. Перемещайте сеноуборочную машину с помощью клавиш со стрелками и стреляйте сеном с помощью клавиши пробела!

Управление машиной и стрельба сеном в сцене редактора Unity

Все должно работать как на GIF-изображении выше.

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

Игровые объекты тюки сена движутся в редакторе Unity

Чтобы исправить это, вы разумно примените триггеры, теги и пару строк кода.

Теги и реакция на физику

Чтобы идентифицировать типы GameObject, вы можете использовать теги. Теги — это справочные слова, такие как «Player» или «Collectible», которые вы можете назначить игровым объектам, чтобы легко их находить и отличать от других игровых объектов. В качестве тега можно использовать любое слово или короткое предложение.

Создать новый тег довольно просто: выберите Edit > Project Settings… в верхнем меню и откройте вкладку Tags and Layers в окне Project Settings. Теперь разверните список тегов, и вы заметите, что в проекте уже есть два предварительно загруженных тега: DestroyHay и DropSheep.

Настройка тегов в окне Project Settings редактора Unity

Нажмите кнопку + под списком тегов, назовите новый тег Hay и нажмите кнопку Save, чтобы добавить этот новый тег в список.

Создание тега в окне Project Settings редактора Unity

После добавления тега Hay закройте окно настроек проекта и выберите Hay Bale в папке RW Prefabs. Откройте раскрывающееся меню Tag прямо под полем имени и выберите Hay.

Выбор тега в настройках игрового объекта редактора Unity

Теперь разница между тюками сена и другими игровыми объектами очевидна: вы можете добавить область, которая разрушает сено при соприкосновении с ним. Добавьте новый пустой игровой объект в Hierarchy и назовите его Triggers. Сбросьте его Transform и добавьте пустой GameObject в качестве его дочернего элемента. Назовите этого потомка Hay Destroyer.

Создание игрового объекта для триггеров в окне Hierarchy редактора Unity

Выберите Hay Destroyer, установите его положение на (X: 0, Y: 4, Z: 68) и добавьте к нему Box Collider. Установите флажок Is Trigger на Box Collider и установите Size на (X: 60, Y: 8, Z: 12). Затем измените тег на DestroyHay. Теперь вы должны увидеть огромный коллайдер в форме прямоугольника, появившийся в представлении сцены, прямо за пределами поля обзора камеры.

Отображение границ коллайдера игрового объекта в окне сцены редактора Unity

Теперь, чтобы этот триггер уничтожил любое сено, вам нужно написать еще один служебный скрипт. Создайте новый сценарий C # внутри RW Scripts, назовите его DestroyOnTrigger и откройте его в редакторе кода. Полностью удалите методы Start и Update и добавьте вместо них это объявление переменной:

public string tagFilter;

Эта строка позволит вам ввести имя любого тега, который уничтожит этот игровой объект.

Теперь добавьте этот метод под только что добавленной переменной:

private void OnTriggerEnter(Collider other) // 1
{
    if (other.CompareTag(tagFilter)) // 2
    {
        Destroy(gameObject); // 3
    }
}

Вот что происходит:

  1. onTriggerEnter — это функция MonoBehaviour, это один из специальных методов, которые движок Unity вызывает в определенных обстоятельствах. В этом случае onTriggerEnter вызывается, когда игровой объект с Rigidbody и Collider входит в область триггера игрового объекта.
  2. Проверяется, есть ли у игрового объекта, входящего в триггер, тег, определенный в tagFilter.
  3. Уничтожить игровой объект, к которому прикреплен этот скрипт.

Сохраните этот скрипт и вернитесь в редактор. Время проверить!

Выберите Hay Bale в RW Prefabs, добавьте компонент Destroy On Trigger и измените Tag Filter на DestroyHay.

Установка тега компоненту скрипта игрового объекта в Unity

Теперь нажмите кнопку play и попробуйте снова коснуться сена. Вы заметите, что любое сено, попавшее в Hay Destroyer, мгновенно уничтожается.

Игровые объекты тюки с сеном движутся и соприкосаются с коллайдером исчезают в окне сцены редактора Unity

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

Скрипты для овец

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

Для начала создайте новый пустой GameObject в окне Hierarchy и назовите его Sheep. Сбросьте его Transform, установите его поворот по оси Y на 180 и добавьте Box Collider и Rigidbody. Установите флажок Is Trigger для Box Collider и измените его центр и размер на (X: 0, Y: 1,4, Z: -0,3) и (X: 2,5, Y: 2, Z: 4) соответственно. Наконец, установите флажок Is Kinematic на Rigidbody.

Теперь овца в Инспекторе должна выглядеть так:

Настройки игрового объекта Sheep в окне Inspector редактора Unity

Перетащите модель Sheep из RW Models на Sheep, чтобы придать ей визуальные эффекты. Назовите игровой объект, который вы только что добавили, Sheep Model, сбросьте его Transform и установите поворот по оси X на -90, чтобы голова выходила из поверхности.

Модель игрового объекта Sheep встает на поверхность в сцене редактора Unity

Теперь эта овца готова к написанию скрипта!

Примечание. До сих пор вы создавали общие скрипты, которые можно повторно использовать для любого игрового объекта или даже других проектов. Скрипт, который вы собираетесь написать, намного более конкретен, потому что его взаимодействие довольно уникально и со временем будет усложняться по мере добавления в игру дополнительных функций.

Создайте новый скрипт C# с именем Sheep в RW Scripts и откройте его в редакторе кода.

Для начала овце просто нужно бежать вперед и исчезнуть, когда ее ударит тюк сена. Добавьте следующие объявления переменных прямо над Start:

public float runSpeed; // 1
public float gotHayDestroyDelay; // 2
private bool hitByHay; // 3

Вот для чего они нужны:

  1. Скорость бега овцы в метрах в секунду.
  2. Задержка в секундах перед тем, как овца будет уничтожена после удара сеном.
  3. Логическое значение, которое принимает значение true, когда овца попала в сено.

Разобравшись с этим, добавьте эту строку в Update:

transform.Translate(Vector3.forward * runSpeed * Time.deltaTime);

Это заставляет овцу бежать к своему прямому вектору (локальной оси Z) со скоростью, установленной в переменной runSpeed.

Затем добавьте этот метод ниже Update:

private void HitByHay()
{
    hitByHay = true; // 1
    runSpeed = 0; // 2

    Destroy(gameObject, gotHayDestroyDelay); // 3
}

Вот суть этого метода:

  1. Установить для hitByHay значение true, это будет полезно, чтобы проверить, был ли уже вызван метод, чтобы он не вызывался дважды или более.
  2. Установить скорость бега на 0, это остановит овцу.
  3. Вы уже видели этот вызов метода, но на этот раз есть дополнительный параметр. Метод Destroy принимает второй параметр — задержку в секундах перед уничтожением игрового объекта. В этом случае используется переменная delay, которую вы добавили выше.

Последняя часть заставляет овцу реагировать на физику, с добавлением следующего кода:

private void OnTriggerEnter(Collider other) // 1
{
    if (other.CompareTag("Hay") && !hitByHay) // 2
    {
        Destroy(other.gameObject); // 3
        HitByHay(); // 4
    }
}

Вот что это делает:

  1. Этот метод вызывается, когда триггер входит в этот игровой объект (или наоборот).
  2. Если объекту GameObject, который попал в этот объект, назначен тег Hay, и овца уже не попала в сено …
  3. Уничтожить другой игровой объект (тюк сена).
  4. Вызвать метод HitByHay, который вы добавили перед этим.

На этом пока что, сохраните скрипт и вернитесь в редактор. Выберите Sheep в Иерархии и добавьте компонент Sheep. Установите Run Speed на 10 и Got Hay Destroy Delay на 1.

Настройка параметров компонента скрипта Sheep в окне Inspector редактора Unity

Теперь запустите воспроизведение сцены, выстрелите в овцу и посмотрите, что произойдет!

Выстреливание в овец сеном в окне воспроизведения игры редактора Unity

Потрясающие! Овца перестает двигаться и исчезает, как вы это и закодировали. Что произойдет, если овца пробежит мимо, а вы ее не пристрелите? Перезапустите сцену и проверьте это.

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

Создайте новый пустой игровой объект как дочерний для Triggers, назовите его Sheep Dropper и сбросьте его Transform. Установите его положение на (X: 0, Y: 4, Z: -54) и добавьте Box Collider с установленным флажком Is Trigger и размером (X: 60, Y: 8, Z: 12). Теперь измените его тег на DropSheep, и у вас будет хороший большой триггер позади машины для сена, готовый к использованию.

Установка игрового объекта с компонентом коллайдера в Unity

Когда овца касается этого триггера, она должна упасть и исчезнуть из поля зрения. Чтобы реализовать это, вам необходимо внести некоторые изменения в скрипт Sheep. Снова откройте его в редакторе кода и добавьте следующие объявления переменных ниже существующих:

public float dropDestroyDelay; // 1
private Collider myCollider; // 2
private Rigidbody myRigidbody; // 3

Они говорят сами за себя, но вот краткий обзор:

  1. Время в секундах до того, как овца будет уничтожена, когда она выйдет за край и начнет падать.
  2. Ссылка на компонент Collider овцы.
  3. Ссылка на Rigidbody овцы.

Теперь назначьте необходимые ссылки, добавив это в Start:

myCollider = GetComponent<Collider>();
myRigidbody = GetComponent<Rigidbody>();

Это находит и кэширует collider и rigidbody овцы для дальнейшего использования.

Затем необходимо настроить коллайдер овцы, чтобы на него повлияла гравитация. Для этого добавьте этот метод:

private void Drop()
{
    myRigidbody.isKinematic = false; // 1
    myCollider.isTrigger = false; // 2
    Destroy(gameObject, dropDestroyDelay); // 3
}

Этот метод прост:

  1. Сделать rigidbody овцы некинематическим, чтобы на него воздействовала сила тяжести.
  2. Отключить триггер, чтобы овца превратилась в твердый объект.
  3. Уничтожить овцу после задержки, указанной в dropDestroyDelay.

Теперь добавьте следующее в onTriggerEnter прямо под существующим оператором if:

else if (other.CompareTag("DropSheep"))
{
    Drop();
}

Если овца была сбита чем-то другим, кроме тюка сена, она проверяет, имеет ли столкнувшийся коллайдер тег DropSheep; Если это так, вызывается Drop.

Теперь сохраните этот скрипт и вернитесь в редактор. Выберите Sheep и измените значение Drop Destroy Delay на 4.

Запустите воспроизведение сцены еще раз и позвольте овце пройти мимо машины, чтобы посмотреть, что произойдет.

Игровой объект Sheep движется и соприкосается с коллайдером в Unity

Работает! Овца теперь падает и исчезает, когда игроку не удается ее спасти. Вот это мотивирует!

Теперь, когда овца действует так, как задумано, перетащите ее из Иерархии в папку RW Prefabs, чтобы превратить ее в префаб, и удалите оригинал из Иерархии.

Это первая часть урока по написанию скриптов. Похвалите себя, вы узнали основы создания скриптов для реализации игрового процесса в Unity.

Куда двигаться дальше?

Вы можете скачать готовый проект, нажав на кнопку «Скачать материалы урока» вверху страницы.

Если вы хотите узнать больше об API Unity, ознакомьтесь с этими полезными ресурсами:

  • Unity’s Scripting Reference
  • Unity Scripting Manual

Когда вы будете готовы сделать еще один шаг в написании скриптов с помощью Unity, ознакомьтесь со второй частью урока, вы пригласите целую стаю пушистых друзей и научитесь:

  • Создавать списки и перебирать их.
  • Обновлять элементы пользовательского интерфейса.
  • Использовать систему событий.
  • Использовать шаблон Singleton.
  • Передавать данные между сценами, чтобы настроить игру.

Мы надеемся, что вам понравился этот урок. Если у вас есть какие-либо вопросы или комментарии, то присоединяйтесь к обсуждению, а также делитесь в соцсетях, чтобы сохранить урок в репостах и закладках.

Автор перевода: Jean Winters

Источник: Introduction to Unity Scripting – Part 1

Смотрите также:

Как сделать интерфейс в Юнити для игрыВведение в создание пользовательского интерфейса на Unity


Как сохранять и загружать данные игры в UnityКак сохранять и загружать данные игры в Unity

Скриптинг на Lua, Урок 1.

Всем Привет! 

Подробная гайд — статься

Чтобы начать учится писать скрипты нужно ознакомится с интерфейсом в Roblox Studio. Это можно будет сделать по гайду который скоро выйдет.

-Чтобы написать первый скрипт нужно создать проект!

1. Заходим в Roblox Studio (Если нету необходимо установить! Инструкцию по установке можно найти в интернет ресурсах!)

2. Создаем проект! Рекомендуется «Classic Baseplate»

3. Запускаем шаблон и идем дальше…

-Как создать скрипт.

1. Открываем окно «Exploer» и ищем там вкладку «ServerScriptService» наводим курсор на нее.

2. У вас появился «+» рядом!

3. Нажимаем на «+» и ищем там самый простой ‘Script’ (Скрин в цитате)

Цитата

image.png.3e3c0014a6015822b90deb57202b89b4.png

-Что делать после создания скрипта

1. Когда вы создали script кликаем на него 2 раза и в пвнеле окон появится ваш скрипт

2. Нажимаем на него и вас встречает фраза «print(‘Hello World’)» что переводится как привет мир!

3. Запускаем игру!

4. У вас не чего не должно было появится! Эта строчка выводит слово в так называемую игровую консоль! Открыть и посмтореть ее можно в: На главной панеле сверху нажимаем «View» и снизу в панеле инструментов нажимаем на «OutPut»

5. Снова запускаем игру! В появившейся панеле «OutPuy» Должна появится фраза Hello World.(Рис.1 (снизу)) Эту фразу в скрипте можно заменить на любою! Это можно сделать зайдя в скрипт и поменяв фразу в ковычках после Print-a!
6. Разберем скрипт!(разбор в циатете)

Цитата

Print(«Hello World»)
Давайте разабем по действиям для рабора!
(1)Print(2)(3)Hello World»)

1. Команда Print — Выводит содержимое в консоль!

2. Скобки () — в емх находится содержимое того что будет выводися например значение цвета состоящие из цифр

3. Двойные кавычки «» — В них указывается текствовое содержимое которое выводится текстом!

-Как создать скрипт который будет делать действие и виден игрокам?

1. Очистим наш скрипт!

2. Создадим самый простой Part с помощью скрипта

3. Перепишем этот скрипт

Instance.new("Part",Workspace)

4. С помощью скрипта зайдя в игру у вас появится по середине карты самый обычный блок

5. Запустим игру и проверим!

6. Разбор скрипта в цитате!

Цитата

Instance.new(«Part»,Workspace)

Разабем по действием разбора

(1)Instance.(2)new(«(3)Part»,(4)Workspace)

1. Экземпляр (добаить)

2. Новый (Экземпляр)

3. Текстовое название эказемпляра

4. Где он заспавнится

Гайд 1 основы скрипта закончен

В сл. гайде рассмотрим Slep. Переменные, Изменения пораметров обьекта по скрипту

Есть вопросы пишите отвечу)

Lua-скрипты пишутся на языке программирования Lua, что очень даже естественно. Lua это интерпретируемый скриптовой язык родом из Бразилии. Год его рождения — 1993-й год. С тех пор он постоянно развивается и расширяет свои возможности. Lua — это язык свободного распространения. По своей функциональности он ближе к JavaScript, но по некоторым компетентным мнениям он более гибкий, чем JS.

 

Скрипты Lua

Скрипты Lua не имеют собственной функции, с которой бы начиналось их выполнение. Это просто список заданных инструкций, которые выполняются по порядку, стартуя с первой.

Скрипты Луа могут быть:

  • простыми и содержать в себе всего одну команду;
  • сложными и содержать в себе десятки, сотни и даже тысячи разных команд.

Все, что разделяет команды между собой, — это символ «;», и то это, скорее, рекомендация, а не предписание. Поэтому команды могут ничем не разделяться.

 

Переменные в скриптах Lua

Скриптинг Lua приспособлен к работе с переменными. Эти переменные можно именовать, используя:

  • латинские символы;
  • разнообразную комбинацию цифр;
  • «нижнее подчеркивание».

Есть 4 требования при наименовании переменных:

  1. Переменные не должны начинаться с цифры.
  2. Регистр имеет значение! К примеру: «xyz», «XYZ» и «Xyz» это разные имена переменных.
  3. Нельзя использовать зарезервированные языком имена.
  4. Нельзя использовать имена, которые начинаются с «нижнего подчеркивания», а продолжаются заглавными буквами. Например: «_XYZ».

Все переменные, как и в любом другом языке, делятся на 2 основных типа и могут быть:

  1. Глобальными. Такая переменная будет функционировать до того времени, пока будет функционировать сама среда, где исполняются скрипты Луа. И такая переменная будет доступна каждой функции Lua в рамках единой среды, где существует сама переменная.
  2. Локальными. Всегда, когда созданная переменная не объявляется «локальной», она будет обозначаться «глобальной». Обозначить переменную локальной возможно, используя слово «local». Например: «local x = 7», где мы создаем локальную переменную «х» и приравниваем ее значение к «7». Локальные переменные видны только в рамках блока, где объявлены. Такими «рамками» могут служить функция или конструкции со словами else, for, while и др.

Важная особенность при работе с переменными: в Lua взаимодействие с локальными переменными осуществляется эффективнее, чем с глобальными. Примите это к сведению, когда нужно «бороться» за производительность.

 

Какую типизацию данных воспринимают скрипты Луа

Сам по себе язык Lua воспринимает следующую типизацию данных:

  1. «nil» (пустое значение);
  2. «boolean» (логика);
  3. «number» (числа);
  4. «string» (строка);
  5. «function» (работа с функциями);
  6. «userdata» (информация о пользователях);
  7. «thread» (работа с потоками);
  8. «table» (работа с таблицами).

Любая переменная готова использовать любой из перечисленных типов — это определяет динамическая типизация языка Lua.

 

Комментарии в скриптах Lua

Комментарии в скриптах Lua могут быть:

  1. Однострочными. Этот вид комментариев определяется 2-мя «минусами»: «- -». Такой комментарий длится, пока не окончится строка. Например: «local x = 5 — — комментарий в одну строку».
  2. Многострочными. Этот вид комментариев обозначается «двумя минусам», но при этом само тело комментария должно быть заключено в двойные квадратные скобки. Например: «local x = 5 — -[[ комментарий в несколько строк]]».

 

Где используются скрипты Lua

Скриптинг Lua не так распространен, как JavaScript, но все равно за долгие годы существования этого языка он нашел последователей и занял свое место. Скрипты Lua применяются в проектах из разных сфер, некоторые из них довольно известные. Например:

  1. В компьютерных видеоиграх, таких как: «Crysis», «Far Cry», «Diablo 3», «STALKER» и др.
  2. В серверной части ММО-игр, таких как: «World of Warcraft», «Аллоды Online» и др.
  3. В графических программах, таких как: «Adobe Photoshop Lightroom» и др.
  4. В движках для игр, например, в «Instead».
  5. В GUI-разработке приложений.
  6. И др.

 

Заключение

Отметим несколько достоинств скриптов Луа:

  1. Скрипты Lua выглядят очень компактными и просто на отлично взаимодействуют с языком программирования С. А это значит, что с этой «парочкой» можно свернуть горы программирования.
  2. Скрипты Луа очень «быстры». По своей скорости они легко конкурируют с Python, C и JavaScript.
  3. Скрипты Lua писать несложно. Сам Луа достаточно простой язык, и около 80% языка вы поймете только потому, что знаете английский.

Да, Lua не самый популярный язык программирования, но он однозначно достоин внимания.

Понравилась статья? Поделить с друзьями:
  • Как написать скрипт юнити
  • Как написать скрипт продаж для холодных звонков
  • Как написать скрипт на телефоне
  • Как написать скрипт на стандофф 2
  • Как написать скрипт на питоне 1000 7