Руководство по скриптам unity

Setting Up Your Scripting Environment

Scripting is an essential ingredient in all applications you make in Unity. Most applications need scriptsA piece of code that allows you to create your own Components, trigger game events, modify Component properties over time and respond to user input in any way you like. More info
See in Glossary
to respond to input from the player and to arrange for events in the gameplay to happen when they should. Beyond that, scripts can be used to create graphical effects, control the physical behaviour of objects or even implement a custom AI system for characters in the game.

This section explains the main concepts that apply to scripting in Unity.

  • Setting Up Your Scripting Environment

  • Scripting Concepts

  • Important Classes

  • Unity Architecture

  • Plug-insA set of code created outside of Unity that creates functionality in Unity. There are two kinds of plug-ins you can use in Unity: Managed plug-ins (managed .NET assemblies created with tools like Visual Studio) and Native plug-ins (platform-specific native code libraries). More info
    See in Glossary

  • The C# Job System

Related pages

See the Unity Learn website’s Scripting section for tutorials on how to use scripting in Unity.

The Knowledge Base Editor section has troubleshooting, guidance on interpreting C# Compiler Errors and tips and tricks.

The Unity Forum also has common scripting questions and answers.

Setting Up Your Scripting Environment

Поведение GameObjectsФундаментальный объект в сценах Unity, который может представлять персонажей, реквизит, декорации, камеры, путевые точки, и более. Функциональность GameObject определяется прикрепленными к нему компонентами. Подробнее
См. в Словарь
контролируется КомпонентыФункциональная часть GameObject. GameObject может содержать любое количество компонентов. В Unity есть много встроенных компонентов, и вы можете создавать свои собственные, написав сценарии, которые наследуются от MonoBehaviour. Подробнее
См. в Словарь
, которые к ним прикреплены. Хотя встроенные компоненты Unity могут быть очень универсальными, вскоре вы обнаружите, что вам нужно выйти за рамки того, что они могут предоставить, чтобы реализовать свои собственные функции игрового процесса. Unity позволяет создавать собственные компоненты с помощью скриптов. Они позволяют запускать игровые события, изменять свойства компонентов с течением времени и реагировать на действия пользователя любым удобным для вас способом.

Unity изначально поддерживает язык программирования C#. C# (произносится как C-sharp) – это язык, являющийся отраслевым стандартом, аналогичный Java или C++.

Кроме того, с Unity можно использовать многие другие языки .NET, если они могут скомпилировать совместимую библиотеку DLL. Дополнительную информацию см. здесь.

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

Создание сценариев

В отличие от большинства других ресурсов, сценарии обычно создаются непосредственно в Unity. Вы можете создать новый сценарий в меню «Создать» в левом верхнем углу панели «Проект» или выбрав Ресурсы > Создать > Сценарий C# в главном меню.

Новый сценарий будет создан в той папке, которую вы выбрали на панели «Проект». Будет выбрано имя нового файла сценария, и вам будет предложено ввести новое имя.

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

Структура файла скрипта

Если дважды щелкнуть ресурс сценария в Unity, он откроется в текстовом редакторе. По умолчанию Unity будет использовать Visual Studio, но вы можете выбрать любой редактор на панели Внешние инструменты в настройках Unity (перейдите в раздел Unity > Настройки).

Первоначальное содержимое файла будет выглядеть примерно так:

using UnityEngine;
using System.Collections;

public class MainPlayer : MonoBehaviour {

// Use this for initialization
void Start () {

}

// Update is called once per frame
void Update () {

}
}

Скрипт устанавливает связь с внутренней работой Unity, реализуя класс, производный от встроенного класса с именем MonoBehaviour. Вы можете думать о классе как о своего рода схеме для создания нового типа Компонента, который может быть присоединен к GameObjects. Каждый раз, когда вы прикрепляете компонент скрипта к GameObject, он создает новый экземпляр объекта, определенного планом. Имя класса берется из имени, которое вы указали при создании файла. Имя класса и имя файла должны совпадать, чтобы можно было присоединить компонент скрипта к GameObject.

Однако главное, на что следует обратить внимание, это две функции, определенные внутри класса. Функция Update — это место для размещения кода, который будет обрабатывать обновление кадра для GameObject. Это может включать в себя движение, инициирование действий и реакцию на ввод пользователя, в основном все, что необходимо обрабатывать с течением времени во время игры. Чтобы функция обновления могла выполнять свою работу, часто полезно иметь возможность устанавливать переменные, читать предпочтения и устанавливать соединения с другими игровыми объектами до того, как произойдет какое-либо игровое действие. Функция Start будет вызываться Unity перед началом игрового процесса (т. е. перед первым вызовом функции Update) и является идеальным местом для любой инициализации.

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

Управление игровым объектом

Как отмечалось выше, сценарий определяет только план для Компонента, поэтому ни один из его кодов не будет активирован, пока экземпляр сценария не будет присоединен к игровому объекту. Вы можете прикрепить скрипт, перетащив ресурс скрипта в GameObject на панели иерархии или в инспекторокно Unity, в котором отображается информация о текущем выбранном игровом объекте, активе или настройках проекта, что позволяет вам проверять и редактировать значения. Дополнительная информация
См. в Словарь
выбранного игрового объекта. В меню «Компонент» также есть подменю «Сценарии», которое будет содержать все сценарии, доступные в проекте, в том числе те, которые вы создали сами. Экземпляр скрипта очень похож на любой другой компонент в Инспекторе:

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

// Use this for initialization
void Start ()
{
Debug.Log("I am alive!");
}

Debug.Log – это простая команда, которая просто выводит сообщение на консоль Unity. Если вы нажмете «Воспроизвести сейчас», вы должны увидеть сообщение в нижней части главного окна редактора Unity и в окне консоли (меню: Окно > Общие > КонсольСокращение от игровая консоль
См. в Словарь
).


  • MonoDevelop заменен Visual Studio с 2018.1

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

Версия: 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

Время на прочтение
13 мин

Количество просмотров 109K

Предисловие

Эта статья будет посвящена новичкам в скриптовании Unity, но не совсем новичкам в синтаксисе JavaScript’а или любого другого подобного языка программирования. Тут надо маленько уточнить что JavaScript который использует Unity немного отличается от оригинального в пользу улучшенной поддержки ООП и называется соответственно Unity JavaScript. В нем например появились классы и их наследование, о чем не знают начинающие разработчики на Unity знакомые с объектно ориентированными возможностями оригинального JavaScript, поэтому отвергают его используя C# или Boo.

Благодарности

В первую очередь хочу сказать огромное спасибо автору написавшему статью Unity — бесплатный кроссплатформенный 3D движок (и браузерный тоже), и урок Unity3D для начинающих — Туториал 1, статьи очень хорошие, но вот продолжения нету уже довольно долго, в связи с этим я хотел бы помочь автору данных статей просвящать хабралюдей на тему Unity и я думаю он будет не против если я напишу апгрейд его урока.

Резюме

Я долго думал с чего начать и в итоге решил – начать с начала. То есть, с чего начинается большинство игр? Нет не правильно не с заставок и логотипов студии производителя, а с главного меню! В этом уроке я подробно расскажу об основных элементах игрового GUI, о том как загружать сцены из скрипта, а также о том как заставить различные скрипты взаимодействовать друг с другом. В этом уроке мы создадим главное меню для «шутера» созданного в уроке: Unity3D для начинающих — Туториал 1, также я расскажу что всетаки делал скрипт в том уроке, мы немного изменим его и научимся настраивать его во время игры, прямо из нашего игрового меню.

1. Labels и GUIStyle

Итак поехали, открываем наш проект который мы создали благодаря уроку. Создаем новую сцену (File -> New scene), далее создадим пустой объект внутри сцены (GameObject -> Create Empty) и назовем его например Menu and settings. Теперь создадим пустой файл JavaScript (Assets -> Create -> JavaScript), перетаскиваем его на наш объект Menu and settings и кликнем на самом скрипте два раза, откроется диалоговое окно редактирования скрипта.

Мы видим что файл скрипта у нас не совсем пустой, в нем находится функция Update, про неё я расскажу позже, пока что удалим её и напишем следующее:

public var welcomeLabel : GUIStyle;   //1

function OnGUI(){       //2
    GUI.Label(new Rect(Screen.width / 2, 0, 50, 20),"Welcome",welcomeLabel);  //3
}

Сохраним изменения и нажимаем Play.
Видим сверху, не совсем по центру, почти незаметное слово Welcom, написанное черным шрифтом:

Но что такое? Там должно быть слово Welcome!
На самом деле последняя буква потерялась потому что мы объявили ширину квадрата в котором написан текст недостаточной для того чтобы влезло все слово.
Но давайте обо всем по порядку, выключаем Play mode.

Если кому не понятно, пункты ниже будут соответствовать комментариям в нашем коде:

  1. Переменная welcomeLabel c типом GUIStyle. Идем во вкладку Hierarchy и выбираем наш GameObject (GO) — Menu and settings, видим что в нашем скрипте появилось новое поле Welcome Label. Разверните его, как видите в нем много дочерних полей, я думаю кто работал с JavaScript’ом и CSS в вебе уже наверное догадались для чего нужны эти свойства.
  2. Функция OnGUI(), она вызывается в каждом кадре для рендеринга и обработки GUI событий, все что связано с GUI необходимо вызывать в этой функции.
  3. Ф-я Label() класса GUI. Первым аргументом в эту функцию мы передаем структуру Rect, по сути это квадрат который задается координатами х и y верхнего левого угла, шириной и высотой, у нас как видим координата х = Screen.width / 2, тоесть ширина экрана деленная на 2, это нужно для того чтобы выровнять текст по центру, вторым аргументом передается текстовая строка «Welcome», и третий аргумент – это стиль с помощью которого мы будем задавать разные параметры нашему Label’у c помощью поля Welcome Label.

Теперь разверните поле Welcome Label и установите следующие параметры:

Нажмите на Play и полюбуйтесь на результат:

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

Лирическое отступление Begin

Вообще в качестве редактора скриптов вы можете использовать любую среду разработки которая нравится вам, все скрипты создаются в папке Assets вашего проекта. Например вы можете использовать свободную среду разработки MonoDevelop, хотя она предназначена в основном для кодинга C# и других .NET языков, для JS тоже сойдет. Она также включена в дистрибутив Unity (чтобы установить её надо поставить галочку перед началом установки Unity), а чтобы скрипты открывались постоянно через эту программу надо зайти в Edit -> Prefences… и в поле External Script Editor указать путь к нашему редактору, также надо синхронизировать все созданные вами скрипты с файлом проекта достаточно нажать Assets -> Sync MonoDevelop Project (кнопку не надо нажимать каждый раз после создания очередного скрипта достаточно нажать один раз, дальнейшие скрипты будут включены в файл проекта автоматически). Не буду описывать все достоинства этого редактора, пусть за меня это сделают скриншоты.

Стандартный редактор:

MonoDevelop:

Лирическое отступление End

2. Buttons и GUISkin

Двигаемся дальше, и модифицируем наш скрипт:

public var welcomeLabel : GUIStyle;
public var customSkin : GUISkin;    //1
public var playGameRect : Rect;     //2
public var optionsRect : Rect;      //2
public var quitRect : Rect;         //2




function OnGUI(){
        GUI.Label(new Rect(Screen.width / 2, 0, 50, 20),"Welcome",welcomeLabel);
           
        GUI.skin = customSkin;                    //3
           
        GUI.Button(playGameRect,"Play Game");     //4
        GUI.Button(optionsRect,"Options");        //4
        GUI.Button(quitRect,"Quit");              //4
           
}

Теперь создадим новый GUISkin, Assets -> Create -> GUI Skin, назовем его Menu Skin, теперь переходим на наш объект Menu and settings и перетаскиваем только что созданный Menu Skin на новое поле Custom Skin, также установим следующие настройки в остальных полях (Play Game Rect, Options Rect, Quit Rect):

Нажимаем Play, результат должен быть следующий:

Перейдем на наш Menu Skin во вкладке Project и чуть увеличим размер шрифта наших кнопок, тоесть разворачиваем поле Buttons и ставим Font Size равным 16, все это можно делать не выходя из Game mode и при выходе из него изменения сохранятся, так как мы меняем свойства префаба.

Теперь разберем наш скрипт:

  1. GUISkin это по сути универсальный набор стандартных настроек GUI позволяет очень гибко менять их.
  2. Про Rect мы уже знаем, только теперь объявляем переменные с модификатором доступа public вне функции дабы получить возможность настраивать их (переменные) из редактора.
  3. Присваиваем настройки нашего GUISkin переменной skin класса GUI, с этого момента все дальнейшие функции класса, будут использовать данный скин, если мы в какой-то момент хотим перестать использовать скин в скрипте и сбросить настройки на стандартные достаточно написать перед этим GUI.skin = null.
  4. Функция Button() по сути ничем не отличается от функции Label, за исключением того что возвращает bool значение (true когда кликаем на кнопку, false естественно во всех остальных случаях).

3. Меню Options и Sliders

Модифицируем скрипт дальше, используем возвращаемое значение ф-ции Button():

public var welcomeLabel : GUIStyle;
public var customSkin : GUISkin;
public var playGameRect : Rect;
public var optionsRect : Rect;
public var quitRect : Rect;


private var optionsMode = false;           //1

public var _bulletImpulse : float = 300;   //2
public var _shootDelay : float = 1;        //2



function OnGUI(){
    if(!optionsMode){                //1
        GUI.Label(new Rect(Screen.width / 2, 0, 50, 20), "Welcome", welcomeLabel);

        GUI.skin = customSkin;
       
        GUI.Button(playGameRect,"Play Game");
               
        if(GUI.Button(optionsRect,"Options")){
            optionsMode = true;             //1
        }
       
        GUI.Button(quitRect,"Quit");
               
    }else{
                               
        GUI.Label(new Rect(Screen.width / 2, 0, 50, 20), "Options", welcomeLabel);
               
        GUI.skin = customSkin;   //5
               
        GUI.Label(new Rect(270, 75, 50, 20),"Bullet Impulse");
        _bulletImpulse = GUI.HorizontalSlider(new Rect(50, 100, 500, 20), _bulletImpulse,10,700);//3
        GUI.Label(new Rect(560, 95, 50, 20), _bulletImpulse.ToString());//4
       
        GUI.Label(new Rect(270, 125, 50, 20),"Shoot Delay");
        _shootDelay = GUI.HorizontalSlider(new Rect(50, 150, 500, 20), _shootDelay, 0.1, 3);//3
        GUI.Label(new Rect(560, 145, 50, 20), _shootDelay.ToString());//4
               
        if(GUI.Button(new Rect(20, 190, 100, 30),"<< Back")){
            optionsMode = false;        //1
        }
       
    }
        
}

  1. Обычно мы привыкли чтобы при открытии какого – либо подменю на экране было только оно, а основное меню исчезало, за этим у нас и будет следить данная переменная.
  2. Собственно это и есть наши игровые опции, мы вернемся к ним позже.
  3. Функция HorizontalSlider() «рисует» (Вот неожиданность!) горизонтальный слайдер, первый принимаемый аргумент (Rect) оставлю без комментариев, второй аргумент – это текущая величина отвечающая за позицию ползунка на слайдере, третий аргумент – левое значение интервала величин, и последний – правое значение, функция возвращает float значение (при передвижении ползунка слайдера) расположенное между левой и правой величиной.
  4. Обратите внимание на последний аргумент в функции Label() – это float значение преобразованное в string функцией ToString(), это важно т.к. компилятор скриптов Unity не умеет преобразовывать число в строку сам, и выдаст ошибку.
  5. GUI.skin сбрасывается при переходе в другое меню, чтобы этого не происходило необходимо присваивать наш customSkin перед рисованием нового меню

Ну давайте же посмотрим что у нас получилось, нажимаем Play и на нашу кнопку Options:

Но что же опять такое? Что за Bullet и Shoot? Должно же быть Bullet Impulse и Shoot Delay! Опять не хватило ширины этих *** квадратов и неужели нам нужно опять лезть в скрипт и менять там ширину?

Нет! Не надо! У нас же есть наш замечательный GUISkin по имени Menu Skin. Не выходя из Play mode заходим в него, разворачиваем поле Label, в опции Text Clipping выбираем значение Overflow и убираем галочку напротив Word Wrap, вуаля, все встало на свои места, выходим из Game mode.

4. Play Game and Quit

Добавляем интерактивности нашим остальным кнопкам:

public var welcomeLabel : GUIStyle;
public var customSkin : GUISkin;
public var playGameRect : Rect;
public var optionsRect : Rect;
public var quitRect : Rect;


private var optionsMode = false;

public var _bulletImpulse : float = 300;
public var _shootDelay : float = 1;

function OnGUI(){
    if(!optionsMode){
        GUI.Label(new Rect(Screen.width / 2, 0, 50, 20),"Welcome",welcomeLabel);

        GUI.skin = customSkin;

        if(GUI.Button(playGameRect,"Play Game")){
            Application.LoadLevel("Test Scene");  //1
        }
           
        if(GUI.Button(optionsRect,"Options")){
            optionsMode = true;
        }
                   
        if(GUI.Button(quitRect,"Quit")){
            Application.Quit();                   //2
        }
                   
    }else{
                                           
        GUI.Label(new Rect(Screen.width / 2, 0, 50, 20), "Options",welcomeLabel);
                   
        GUI.skin = customSkin;
                   
        GUI.Label(new Rect(270, 75, 50, 20),"Bullet Impulse");
        _bulletImpulse = GUI.HorizontalSlider(new Rect(50, 100, 500, 20),_bulletImpulse,10,700);
        GUI.Label(new Rect(560, 95, 50, 20),_bulletImpulse.ToString());
           
        GUI.Label(new Rect(270, 125, 50, 20),"Shoot Delay");
        _shootDelay = GUI.HorizontalSlider(new Rect(50, 150, 500, 20),_shootDelay,0.1,3);
        GUI.Label(new Rect(560, 145, 50, 20),_shootDelay.ToString());
                   
        if(GUI.Button(new Rect(20, 190, 100, 30),"<< Back")){
            optionsMode = false;
        }
           
    }  
                           
}

Если вы войдете в Play mode и попробуете понажимать на эти кнопки, то скорее всего при нажатии на Play Game в консоли (Window -> Console) появится ошибка, а при нажатии на Quit вообще ничего не произойдет, давайте разберемся почему:

  1. Ф-я LoadLevel() класса Application загружает сцену по имени “Test Scene” (так я назвал сцену из урока Unity3D для начинающих — Туториал 1), в эту функцию можно так же передавать номер сцены. У вас должно быть возник вопрос: где же взять этот номер? Все просто, cохраните вашу сцену если вы еще этого не сделали, File -> Save Scene As… и назовите её Menu Scene, далее идем в File -> Build Settings… и перетаскиваем в появившееся окошко сначала нашу сцену Menu Scene, затем Test Scene.

    С правой стороны от имени сцены мы видим её порядковый номер (по умолчанию первой всегда загружается сцена с номером 0). Кто еще не догадался наша Test Scene не хотела грузиться потому что она не была зарегистрирована в Build Settings, но теперь все будет ОК. Закройте окошко Build Settings, войдите в Play mode и нажмите на кнопку Play Game. Ура! Наша сцена загружается!

  2. Но кнопка Quit по прежнему не работает. Не беспокойтесь, она и не будет работать если проект запускается в редакторе либо в web плеере. Для того чтобы кнопка заработала нужно чтобы наш проект стал самостоятельным приложением, для этого надо его «построить» и запустить. Для этого заходим в Build Settings и нажимаем на кнопку Build And Run, указываем папку где будет храниться готовое приложение, сохраняем, выбираем настройки, запускаем, видим наше главное меню, и нажимаем Quit, о чудо приложение закрывается.

5. DontDestroyOnLoad и дригие нехорошие слова

Для начала давайте разберем скрипт из урока Unity3D для начинающих — Туториал 1 и выясним какие настройки он использует и для чего он их использует:

public var bulletImpulse = 300;   //1
public var shootSpeed;            //2
public var bullet : GameObject;   //3
 
public var lastShotTime : float;  //4
 
function Start() {                //5
    lastShotTime = 0;
}

function Update () {              //6
 
    if (Input.GetKey(KeyCode.Mouse0)) {    //7
        if (Time.time>(lastShotTime + shootSpeed)){//8
                var bull_clone : GameObject;   //9
                       
                bull_clone = Instantiate(bullet, transform.position, transform.rotation);//10
                Physics.IgnoreCollision(bull_clone.collider, collider);//11
                bull_clone.rigidbody.AddForce(transform.forward*bulletImpulse, ForceMode.Impulse);//12
                lastShotTime = Time.time;//13
        }
    }
}

  1. импульс который дает пинок под зад передается нашей пули
  2. shootSpeed, не очень удачное название для данного параметра т.к. это по сути задержка между выстрелами, в скрипте MainMenu опцию которую в последствии нам предстоит получить вместо этой я назвал _shootDelay
  3. собственно сама пуля, может быть как префабом, так и объектом внутри сцены
  4. время последнего выстрела
  5. Ф-я Start() вызывается ОДИН раз перед ПЕРВЫМ методом Update
  6. Ф-я Update() вызывается в каждом кадре (вообще в официальной документации все функции взаимодействующие с физикой рекомендуют прописывать в функции FixedUpdate() во избежание разнообразных багов с физикой, но для нашего проектика это не критично так как он очень маленький).
  7. Если нажата левая кнопка мыши.
  8. И если текущее время больше времени последнего выстрела + задержка между выстрелами.
  9. Объявляем переменную с типом GameObject.
  10. Ф-я Instantiate() клонирует объект и возвращает его c заданной позицией и углом поворота в мировом пространстве. Cобственно первый аргумент bullet, это и есть копируемый объект, тоесть наша пуля, вторым аргументом мы обращаемся к классу transform игрового объекта к которому прикреплен скрипт(в нашем случае это объект Player), собственно класс Transform хранит информацию о физическом расположении игрового объекта, из него мы получаем две переменные необходимые нам, это position – хранящую позицию в мировом пространстве, и rotation – хранящую угол поворота.
  11. Обращаемся к объекту Physics и вызываем функцию IgnoreCollision которая заставляет его игнорировать все столкновения (коллизии) между коллайдером объекта (Player) к которому прикреплен скрипт, и коллайдерами клонов нашей пули, все это значит что между этими двумя объектами больше не будут происходить физические взаимодействия, и наш Player просто напросто будет ходить сквозь шары — клоны.
  12. обращаемся к объекту rigidbody нашей пули, который контролирует позицию объекта через физическую симуляцию, и вызываем функцию AddForce() которая добавит определенное физическое воздействие (в нашем случае импульс) на наш объект, первый параметр это вектор, в нашем случае направленный вперед относительно трансформации нашего Player’a и помноженный на силу импульса, второй параметр это режим силы.
  13. сохраняем текущее время, теперь — это время последнего выстрела

Итак перерабатываем этот поток информации и выясняем что нам по нужны всего лишь две переменные (bulletImpulse и shootSpeed) и как многие уже догадались нам нужно получить их из GameObject’а Menu and settings, а точнее из скрипта который к нему прикреплен.

Но вот получилась какая незадача. Для того чтобы получить нужные нам данные из скрипта объекта Menu and settings он должен находиться в одной сцене с нашим объектом Player, и как многие уже могли заметить, при нажатии нашей кнопки Play Game все объекты из сцены Menu Scene уничтожаются и во вкладке Hierarchy у нас появляются объекты из второй сцены (Test Scene).

Победить этот недуг нам поможет функция DontDestroyOnLoad(). Её достаточно вызвать один раз в функции Awake() которая вызывается при инициализации скрипта, это своеобразный конструктор для него.

Добавим в скрипт MainMenu следующую функцию:

function Awake(){
    DontDestroyOnLoad(this);
}

Войдем в Play mode и нажмем на Play Game. Круто! Меню не исчезло и накладывается у нас теперь поверх всего, это означает что объект Menu and settings не уничтожился, а так же это означает его присутствие во вкладке Hierarchy.

Но меню же теперь постоянно видно! Не порядок и с этим надо бороться, а следовательно модифицируем скрипт (это последний раз):

public var welcomeLabel : GUIStyle;
public var customSkin : GUISkin;
public var playGameRect : Rect;
public var optionsRect : Rect;
public var quitRect : Rect;


private var optionsMode = false;
private var menuMode = true;   //1
private var gameMode = false;  //1

public var _bulletImpulse : float = 300;
public var _shootDelay : float = 1;

function Awake(){
    DontDestroyOnLoad(this);
}


function OnGUI(){
    if (Input.GetKey(KeyCode.Escape)){  //2
        menuMode = true;                //1
        optionsMode = false;  
        Time.timeScale = 0;             //3
                
        if(gameMode){                   //1
            var ml = GameObject.Find("Player").GetComponent(MouseLook);  //4
            ml.enabled = false;  //4
        }
    }

    if(menuMode){
        if(!optionsMode){                       
                        
            GUI.Label(new Rect(Screen.width / 2, 0, 50, 20), "Welcome",welcomeLabel);
                
            GUI.skin = customSkin;
                        
            if(!gameMode){              //1
                if(GUI.Button(playGameRect, "Play Game")){
                    menuMode = false;   //1
                    gameMode = true;    //1
                    Time.timeScale = 1; //3
                    Application.LoadLevel("Test Scene");
                }
            }else{
                if(GUI.Button(playGameRect,"Resume")){
                    var _ml = GameObject.Find("Player").GetComponent(MouseLook);//4
                    _ml.enabled = true; //4
                    Time.timeScale = 1; //3
                    menuMode = false;   //1
                }
            }
                        
            if(GUI.Button(optionsRect,"Options")){
                optionsMode = true;
            }
                        
            if(GUI.Button(quitRect,"Quit")){
                Application.Quit();
            }
                        
        }else{
                                                        
            GUI.Label(new Rect(Screen.width / 2, 0, 50, 20),"Options",welcomeLabel);
                        
            GUI.skin = customSkin;
                        
            GUI.Label(new Rect(270, 75, 50, 20), "Bullet Impulse");
            _bulletImpulse = GUI.HorizontalSlider(new Rect(50, 100, 500, 20), _bulletImpulse,10,700);
            GUI.Label(new Rect(560, 95, 50, 20), _bulletImpulse.ToString());
                        
            GUI.Label(new Rect(270, 125, 50, 20), "Shoot Delay");
            _shootDelay = GUI.HorizontalSlider(new Rect(50, 150, 500, 20), _shootDelay,0.1,3);
            GUI.Label(new Rect(560, 145, 50, 20), _shootDelay.ToString());
                        
            if(GUI.Button(new Rect(20, 190, 100, 30), "<< Back")){
                optionsMode = false;
            }
        
        }
    }

}

  1. Для того чтобы меню было более гибким оно должно знать в каком состоянии сейчас находится.
  2. Добавим в скрипт возможность вызывать меню по нажатию клавиши Escape.
  3. Когда мы вызываем меню во время игры, она должна вставать на паузу, самый простой способ это сделать, обнулить переменную timeScale класса Time, по сути своей эта переменная отвечает за скорость игрового процесса, где значение 1 – нормальная скорость, значения меньше 1 – slo-mo, выше 1 – быстрая скорость, и 0 – пауза
  4. Ну вот собственно и мы и добрались до взаимодействия между скриптами, данная конструкция выполняет следующие действия: ф-я Find() класса GameObject ищет GO по имени и возвращает его, следом идет функция GetComponent() которая находит класс в нашем вернувшемся GO (класс MouseLook) и возвращает его, затем мы присваиваем bool значение переменной enabled внутри этого класса что позволяет включить либо отключить скрипт MouseLook (true и false соответственно). Все эти операции нужны нам для того чтобы при переходе в главное меню наш Player не мог вертеть «головой» (перевод игры в режим паузы не поможет, можете проверить закомментировав данные строчки).

6. Получаем настройки

Ну наконец то, мы дошли до финишной прямой все что нам осталось сделать, это получить настройки из объекта Menu and settings. Модифицируем скрипт из урока Unity3D для начинающих — Туториал 1:

//public var bulletImpulse = 300;   //1
//public var shootSpeed : float = 1;  //1
public var bullet : GameObject;  

public var lastShotTime : float;  

function Start() {          
        lastShotTime = 0;
}

function FixedUpdate () {    

    if (Input.GetKey(KeyCode.Mouse0)) {
       
        var go : GameObject = GameObject.Find("Menu and settings");//2
        var shootSpeed : float = go.GetComponent(MainMenu)._shootDelay;//3     
                       
        if (Time.time>(lastShotTime + shootSpeed)) {  
                               
            var bulletImpulse : float = go.GetComponent(MainMenu)._bulletImpulse;   //3
                                                                       
            var bull_clone : GameObject;  
                                                                                                                       
            bull_clone = Instantiate(bullet,transform.position,transform.rotation);  
                                                                                                                                                                                                                               
            Physics.IgnoreCollision(bull_clone.collider, collider);
            bull_clone.rigidbody.AddForce(transform.forward*bulletImpulse, ForceMode.Impulse);
                                                                                                                                               
            lastShotTime = Time.time;  

        }
    }
}

  1. Здесь эти переменные больше нам не потребуются так мы получим их значения из другого скрипта, я закомментировал их чтобы было понятнее.
  2. Получаем объект Menu and settings.
  3. Получаем компонент MainMenu, и его переменные.

Все, можете запускать и проверять. Наиболее явное безумие начинается при уменьшении опции Shoot Delay до минимума, шары должны вылетать из вашего Player’a с большой частотой, словно пули из пулемета. Ну в общем, думаю теперь вы сами разберетесь, ведь теперь вы владеете силой, силой скриптов Unity.

Заключение

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

Cover image for Unity 3D C# scripting cheatsheet for beginners

Vishnu Sivan

Vishnu Sivan

Posted on Apr 30, 2022

• Updated on Jun 16, 2022



 



 



 



 



 

 

Unity3D is one of the best cross-platform game engines with AR VR integration capability and a powerful rendering engine (HDRP, URP). Moreover the assets store supports free and paid asset purchases. Unity uses C# as the scripting language to implement the game logic. You can handle object instantiation, manipulation, user interactions, UI control management using the C# scripting mechanism. The highlight of unity scripting is the ease of object access through inspector and the MonoBehaviour life cycle methods.

Scripting is the entity that controls the GameObjects and tells the behavior and interaction of the game objects in the scene. The strength of Unity scripting is its life cycle methods and the APIs for gameObject manipulations. You can consider everything in the Unity scene as GameObjects and refer to it in the script via inspector or using the GetComponent method.

This tutorial summarizes the commonly used features in Unity using C#.

Let’s get started!

Getting Started

Our first script

Unity uses C# as the primary scripting language. You can also write your code in Javascript but most of them prefer C# due to its simplicity. Unity operates only with object-oriented scripting languages. Variables, functions, and classes are the primary building block of any language. The following is a basic script in Unity with a log message.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class HelloWorld : MonoBehaviour
{
    //Variables
    //Functions
    //Classes    
    // Start is called before the first frame update
    void Start()
    {
        Debug.Log("Hello World");
    }    
    // Update is called once per frame
    void Update()
    {

    }
}

Enter fullscreen mode

Exit fullscreen mode

Here, we can see HelloWorld class, Start() and Update() functions and a log message.

1. Variables

It is the name of a memory location which holds values and references of an object. Like any object orient programming language, the variable declaration contains the accessibility level (scope). It can be public, private or protected. 
Unity made the object referencing simple by showing the public variables in the inspector. So, the user can easily provide values or references to that variable from the inspector. 

If we want to refer to any gameObject in the script then make its visibility public or put a SerializeField tag there.

public class HelloWorld : MonoBehaviour
{
    public GameObject gameObject1; 
    [SerializeField]
    private GameObject gameObject2;
    private GameObject gameObject3;
}

Enter fullscreen mode

Exit fullscreen mode

Here gameObject1 and gameObject2 will be visible in the inspector and the gameObject3 can be referred to inside the script only.

2. Classes

Classes are the blueprint of the objects. It is a template that wraps variables and functions together.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class HelloWorld : MonoBehaviour
{
    public GameObject gameObject1;
    private GameObject gameObject2;    
    // Start is called before the first frame update
    void Start()
    {
        Display();
    }    
    // Update is called once per frame
    void Update()
    {

    }    
    void Display()
    {
        Debug.Log("Hello World");
    }
}

Enter fullscreen mode

Exit fullscreen mode

3. Functions

Functions are a set of codes executed to accomplish a specific task. It helps to create reusable codes and implement modularity in your app. Also, we use functions to make our codes readable and portable. 

Unity has a couple of life cycle methods such as Awake(), Start(), Update(), and these methods call automatically when some predefined conditions are met.

// Called when the script is being loaded
private void Awake() {}
// Called every time the object is enabled
private void OnEnable() {}
// Called on the frame when the script is enabled
private void Start() {}
// Called once per frame
private void Update() {}
// Called every frame after Update
private void LateUpdate() {}
// Called every Fixed Timestep
private void FixedUpdate() {}
// Called when the renderer is visible by any Camera
private void OnBecameVisible() {}
// Called when the renderer is no longer visible by any Camera
private void OnBecameInvisible() {}
// Allows you to draw Gizmos in the Scene View
private void OnDrawGizmos() {}
// Called multiple times per frame in response to GUI events
private void OnGUI() {}
// Called at the end of a frame when a pause is detected
private void OnApplicationPause() {}
// Called every time the object is disabled
private void OnDisable() {}
// Only called on previously active GameObjects that have been destroyed
private void OnDestroy() {}

Enter fullscreen mode

Exit fullscreen mode

  • Awake is called before the scene gets initialized.
  • Start is called after the scene object creation.
  • Update is called once per frame. 
  • FixedUpdate is similar to Update but called in equal intervals.
  • LateUpdate is similar to Update but triggered at end of the frame.

Script lifecycle overview

Script lifecycle overview
Image credits docs.unity3d.com

4. GameObject Manipulation

GameObject is the core component of a Unity project. All objects such as light, UI and 3D models are derived from GameObjects class. This is the parent class for all objects we are using in a unity scene. 

In Unity, we can interact with the GameObjects in two ways - through the inspector and using a script. If you want to change the object position then you can easily do it through the inspector window. Also, you can change the render properties and add extra components such as Rigidbody and custom scripts through the inspector. You can do the same through a custom script if required.

// Create a GameObject
Instantiate(GameObject prefab);
Instantiate(GameObject prefab, Transform parent);
Instantiate(GameObject prefab, Vector3 position, Quaternion rotation);
Instantiate(bullet);
Instantiate(bullet, bulletSpawn.transform);
Instantiate(bullet, Vector3.zero, Quaternion.identity);
Instantiate(bullet, new Vector3(0, 0, 10), bullet.transform.rotation);

// Destroy a GameObject
Destroy(gameObject);

// Finding GameObjects
GameObject myObj = GameObject.Find("NAME IN HIERARCHY");
GameObject myObj = GameObject.FindWithTag("TAG");

// Accessing Components
Example myComponent = GetComponent<Example>();
AudioSource audioSource = GetComponent<AudioSource>();
Rigidbody rgbd = GetComponent<Rigidbody>();

Enter fullscreen mode

Exit fullscreen mode

5. Input System

The input system is the crucial component in every game that we have played. It might be a keyboard, joystick, or touch. Unity has a Conventional Game Input to access input in your games. 

Unity also provides a couple of methods to access the input system in our script. To read an axis, we can use Input.GetAxis with «Horizontal» / «Vertical» value as the argument to access arrow buttons on the keyboard and A, W, S, D keys on the joystick.

if (Input.GetKeyDown(KeyCode.Space)) { 
    Debug.Log("Space key was Pressed"); 
}
if (Input.GetKeyUp(KeyCode.W)) { 
    Debug.Log("W key was Released"); 
}
if (Input.GetKey(KeyCode.UpArrow)) { 
    Debug.Log("Up Arrow key is being held down"); 
}
/* Button Input located under Edit >> Project Settings >> Input */
if (Input.GetButtonDown("ButtonName")) { 
    Debug.Log("Button was pressed"); 
}
if (Input.GetButtonUp("ButtonName")) { 
    Debug.Log("Button was released"); 
}
if (Input.GetButton("ButtonName")) { 
    Debug.Log("Button is being held down"); 
}

Enter fullscreen mode

Exit fullscreen mode

6. Vector

Vector is a mathematical concept that holds both magnitude and direction. It is useful to describe some properties such as the position and velocity of a moving object in your game, or the distance between two objects. Unity implements Vector2 and Vector3 classes for working with 2D and 3D vectors.

vector
Image credits reaconverter.com
X = Left/Right Y = Up/Down Z = Forward/Back

Vector3.right /* (1, 0, 0) */   
Vector2.right /* (1, 0) */
Vector3.left /* (-1, 0, 0) */   
Vector2.left /* (-1, 0) */
Vector3.up /* (0, 1, 0) */      
Vector2.up /* (0, 1) */
Vector3.down /* (0, -1, 0) */   
Vector2.down /* (0, -1) */
Vector3.forward /* (0, 0, 1) */
Vector3.back /* (0, 0, -1) */
Vector3.zero /* (0, 0, 0) */    
Vector2.zero /* (0, 0) */
Vector3.one /* (1, 1, 1) */     
Vector2.one /* (1, 1) */
float length = myVector.magnitude /* Length of this Vector */
myVector.normalized /* Keeps direction, but reduces length to 1 */

Enter fullscreen mode

Exit fullscreen mode

7. Time

Unity supports time-related operations through its Time library. Time.time, Time.deltaTime and Time.timeScale are the most common APIs to work with time in your project. 

  • Time.time returns the time at the beginning of the current frame.
  • Time.deltaTime returns the time difference between the current and last frame in seconds.
  • Time.timeScale represents scale at which time elapses.
// The time in seconds since the start of the game
float timeSinceStartOfGame = Time.time;
// The scale at which the time is passing
float currentTimeScale = Time.timeScale;
// Pause time
Time.timeScale = 0;
// The time in seconds it took to complete the last frame 
// Use with Update() and LateUpdate()
float timePassedSinceLastFrame = Time.deltaTime;
// The interval in seconds at which physics and fixed frame rate updates are performed and use with FixedUpdate()
float physicsInterval =  Time.fixedDeltaTime;

Enter fullscreen mode

Exit fullscreen mode

8. Physics Events

Unity has a sophisticated system to implement physics in your project. It various physics attributes to the gameObjects such as gravity, acceleration, collision and other forces.

/* Both objects have to have a Collider and one object has to have a Rigidbody for these Events to work */
private void OnCollisionEnter(Collision hit) {    
  Debug.Log(gameObject.name + " hits " + hit.gameObject.name); 
}
private void OnCollisionStay(Collision hit) {  
  Debug.Log(gameObject.name + " is hitting " + hit.gameObject.name); 
}
private void OnCollisionExit(Collision hit) { 
  Debug.Log(gameObject.name + " stopped hitting " + hit.gameObject.name); 
}
// Trigger must be checked on one of the Colliders
private void OnTriggerEnter(Collider hit) {    
  Debug.Log(gameObject.name + " just hit " + hit.name); 
}
private void OnTriggerStay(Collider hit) { 
  Debug.Log(gameObject.name + " is hitting " + hit.name); 
}
private void OnTriggerExit(Collider hit) { 
  Debug.Log(gameObject.name + " stopped hitting " + hit.name); 
}

// For 2D Colliders
private void OnCollisionEnter2D(Collision2D hit) { }
private void OnCollisionStay2D(Collision2D hit) { }
private void OnCollisionExit2D(Collision2D hit) { }
private void OnTriggerEnter2D(Collider2D hit) { }
private void OnTriggerStay2D(Collider2D hit) { }
private void OnTriggerExit2D(Collider2D hit) { }

// Ray casting to detect the collision
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast(ray, out hit, 100)){
  Debug.DrawLine(ray.origin, hit.point);
  Debug.Log("Hit: " + hit.collider.name);
}

Enter fullscreen mode

Exit fullscreen mode

9. Rendering materials

Materials tell how a surface should be rendered in the scene. The material contains references to shaders, textures, color, emission and more. Every material requires a shader for rendering the content and the attributes available for that may vary on different shader values.

[SerializeField] Material material;
[SerializeField] Texture2D texture;
[SerializeField] Color color = Color.red;
// Start is called before the first frame update
void Start() {
    MeshRenderer meshRenderer = GetComponent<MeshRenderer>();
    // Changing material, texture, color and shader at runtime
    meshRenderer.material = material;
    meshRenderer.material.mainTexture = texture;
    meshRenderer.material.color = color;
    meshRenderer.material.SetColor("_Color", Color.blue);
    meshRenderer.material.EnableKeyword("_EMISSION");
    meshRenderer.material.SetColor("_EmissionColor", Color.yellow);
    meshRenderer.material.shader = Shader.Find("Standard (Specular setup)");
}

Enter fullscreen mode

Exit fullscreen mode

10. Lighting

Lighting is a mandatory component in any Unity scene. All unity scenes contain a directional light component in it by default. Unity has four types of lights - directional, points, spot and area lights

[SerializeField] LightType lightType = LightType.Directional;
Light lightComp = null;
// Start is called before the first frame update
void Start() {
 GameObject lightGameObject = new GameObject("The Light");
 lightComp = lightGameObject.AddComponent<Light>();
 lightComp.color = Color.blue;
 lightComp.type = lightType;
 lightGameObject.transform.position = new Vector3(0, 5, 0);
}
void Update() {
 if (Input.GetKey(KeyCode.UpArrow)) 
    lightComp.GetComponent<Light>().enabled = true; 
 if (Input.GetKey(KeyCode.DownArrow)) 
    lightComp.GetComponent<Light>().enabled = false;
}

Enter fullscreen mode

Exit fullscreen mode

11. Coroutine

A coroutine is like a background activity which can hold the execution of codes after the yield statement until it returns a value.

// Create a Coroutine 
private IEnumerator CountSeconds(int count = 10)
{
  for (int i = 0; i <= count; i++) {
    Debug.Log(i + " second(s) have passed");
    yield return new WaitForSeconds(1.0f);
  }
}

// Call a Coroutine 
StartCoroutine(CountSeconds());
StartCoroutine(CountSeconds(10));

// Store and call a Coroutine from a variable 
private IEnumerator countSecondsCoroutine;countSecondsCoroutine = CountSeconds();
StartCoroutine(countSecondsCoroutine);

// Stop a stored Coroutine 
StopCoroutine(countSecondsCoroutine);
// Coroutine Return Types 
// Waits until the next Update() call
yield return null; 
// Waits until the next FixedUpdate() call
yield return new WaitForFixedUpdate(); 
// Waits until everything this frame has executed
yield return new WaitForEndOfFrame(); 
// Waits for game time in seconds
yield return new WaitForSeconds(float seconds); 
// Waits until a custom condition is met
yield return new WaitUntil(() => MY_CONDITION); 
// Waits for a web request
yield return new WWW("MY/WEB/REQUEST"); 
// Waits until another Coroutine is completed
yield return StartCoroutine("MY_COROUTINE");

Enter fullscreen mode

Exit fullscreen mode

12. Animation

It is an easy task to create animations in Unity. Unity made it simple with the help of Animator controls and Animation Graph. Unity calls the animator controllers to handle which animations to play and when to play them. The animation component is used to playback animations. 

It is quite simple to interact with the animation from a script. First, you have to refer the animation clips to the animation component. Then get the Animator component reference in the script via GetComponent method or by making that variable public. Finally, set enabled attribute value to true for enabling the animation and false for disabling it.

[SerializeField] GameObject cube;
cube.GetComponent<Animator>().enabled = true;
cube.GetComponent<Animator>().SetTrigger("Enable");
cube.GetComponent<Animator>().ResetTrigger("Enable");
cube.GetComponent<Animator>().SetInteger("animId", 1);

Enter fullscreen mode

Exit fullscreen mode

13. Hotkeys

Hotkeys
Image credits patreon.com

Thanks for reading this article.

If you enjoyed this article, please click on the heart button ♥ and share to help others find it!

To get the article in pdf format: Unity3d C# Cheatsheet.pdf

The article is also available on Medium

If you are interested in further exploring, here are some resources I found helpful along the way:

codemaker2015/unity3d-cheat-sheet: Unity 3D Cheat Sheet with examples

Понравилась статья? Поделить с друзьями:
  • Отчет оо2 для школ 2020 инструкция
  • Уфнс по белгородской области официальный сайт руководство по
  • Coq10 инструкция по применению на русском языке отзывы
  • Скачать бесплатно руководство хаммер
  • Зубной гель для кошек cliny инструкция по применению