Туториал 1: 2Д игра - ловилка на Юнити (новичок). Часть 1.

Вступление:

Это туториал по Юнити 3Д для новичков. На самом деле на Ютубе можно найти довольно много видео-туториалов. Но в своем большинстве они показались для меня не особо эффективными. Было не так много туториалов, которые я действительно понимал без знания основ Юнити. Здесь я буду делать относительные простые туториалы в текстовой форме. На самом деле одна из моих целей это поучить английский язык, поэтому эти туториалы обратный перевод с моих туториалов на английском языке. Первый туториал будет о игре - ловилке в 2Д. Для простоты используется встроенная в Юнити физика Physic2D. Надеюсь, что Юнити уже установлена у вас. В туториалах на то время я использовал версию 5.3.5. На тот момент это была последняя стабильная версия. Я обновил скачиваемый пакет до версии 5.5.1. Некоторые скриншоты будут выглядеть немножко по другому, но это не особо критично. Также советую использовать для обучения актуальную версию Юнити.

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

1. Шаг

- Запускаете Юнити. В стартовом окошке выбираете New
старт Юнити

- Даёте название проекту
- Выбираете локацию для записи
- Выбираете 2D
- Нажимаете Create Project
новый проект

Через некоторое время откроется редактор. Важные части для нас будут:
1. Сцена окно, где будет делаться игровая сцена
2. Камера эта область показывает видимую область сцены через камеру
3. Иерархия окно со списком игровых объектов в сцене
4. Инспектор настройка выбранного игрового объекта
5. Проект корневая система папок
6. Ассеты папки, модели, звуки, спрайты, скрипты и тд., то из чего делаете игру
7. Сцена ярлык окошка сцены
8. Игра ярлык игровой камеры
9. Play/Pause/StepPlay кнопки запуска и остановки игры
редактор Юнити
Вид редактораа можно настроить по своему вкусу. Я пока оставлю стандартный вид.

2. Шаг

Для игры понадобится 4 картинки ("земля", "сачок", "плохой предмет", "хороший предмет").
1. Возможность
Как я уже и говорил, можете скачать мою картинку( Картинка). Надо будет импортировать картинку в Юнити. Правый клик Assets и выбираете Import New Asset... Идете в папку куда скачали картинку, выбираете её catch2DImage и нажимаете Import.
импорт картинки

Картинка должна появится в окошке Assets. Но нам надо 4 картинки для этого туториала ("земля", "сачок", "плохой предмет", "хороший предмет"). Мы можем указать Юнити, что это multiple (многочисленная) картинка и мы сможем выделить с неё 4 картинки. Выберите catch2DImage в Assets. Потом идете в Inspector и ставите Sprite Mode на Multiple. Кликаете на Apply.
настройка спрайта

Теперь можно выделить 4 нужные картинки. Картинка должна быть выделенна. Идете опять в Inspector и кликаете на Sprite Editor.
редактор спрайта

Откроется новое окошко Sprite Editor. Кликаете на Slice. Оставляете все как стоит и кликаете на Slice кнопку. Кликаете на Apply.Над каждой картинкой должен появится четырехугольник. Временами приходится поправить его размер. Закрываете окошко Sprite Editor.
верстка спрайта

Теперь можно развернуть картинку в Assets. Если все получилось, то вы должны увидеть 4 картинки в развернутом виде.
атлас из спрайта

2. Возможность
Можно использовать и свои картинки. Просто импортируете 4 своих картинки в Юнити. Правый клик в окошко Assets и выбираете Import New Asset... Идёте в вашу папку, выбираете нужные картинки и нажимаете Import.
альтернативный импорт

3. Возможность
Другой путь для импорта объектов в Юнити это просто перетаскивание файлов (drag&drop) в окошко Assets.

3. Шаг

Сделаем землю для игры. Кликаете на картинку земли (это зеленый квадратик по задумке) и перетаскиваете её в Scene. Проверьте, что rectangle tool включен и растяните картинку по сцене (левый клик на края и тяните их). Выберите в окошке Hierarchy catch2DImage_2 правй клик на неё и смените (rename) имя на Ground. Идите в Inspector и измените Order in Layer на 100.
создание земли

Order in Layer:

Order in Layer важен для отрисовки. Картинки с большим Order in Layer рисуются сверху картинок с меньшим Order in Layer. Это число может быть и негативное, тогда 0 будет сверху -1, -10, ...
Нажимаете Play старта сцены. Нажимаете Play повторно для возвращения назад к Scene.

Пока у нас просто одна картинка в сцене. Мы видим её, но другие GameObjects (игровые объекты) не могут взаимодействовать с ней. Нам надо добавить физический компонент (physics2D) Box Collider2D к ней. Выберите Ground в Hierarchy, идите в Inspector. Нажмите на Add Component -> Physics2D -> Box Collider 2D. Наш Ground может теперь взаимодействовать с другими Collider 2D в игровом мире.

Collider:

Collider это физическое тело для игрового объекта. Смотрите тут Unity Manual для подробностей.
добавить коллайдер 2Д

Земля готова.

4. Шаг

Теперь сделаем игрока (сачок). Большинство шагов совпадает с созданием Ground.
- Добавьте сачок в сцену (перетащите картинку сачка из Assets в Scene)
- Настройте размер (убедитесь, что rectangle tool включен (иконка слева наверху: слева от Pivot))
- Выберите сачок в Hierarchy и назовите его как Player (правый клик и rename)
- Перейдите в Inspector (Player должен быть выделен) и добавьте Box Collider 2D (кликните на Add Component)
- Наш Player будет двигаться. Ему надо дополнительный 2Д-физический компонент Rigidbody2D.

Rigidbody:

Физический движок Юнити может контролировать GameObjects с Rigidbodies. Rigidbodies нужны для физических вычислений. Смотрите Unity Manual для подробностей.
- Перейдите в Inspector от Player и добавьте Rigidbody 2D (кликните на Add Component -> Physics 2D -> Rigidbody2D). Поставьте Interpolate на Interpolate (для плавного движения).
- В Inspector от Player измените Tag на Player.

Tag:

Tag используется для идентификации GameObject. Юнити работает с Tag быстрее чем с именем. Смотрите Unity Manual для информации.
- Order in Layer можно оставить равным 0.
создание игрока

Запустите сцену. сачок должен начать падать и потом остановиться на земле. Нажмите на старт повторно и вернитесь к сцене.

Наш Player должен двигаться налево и направо. Вариантов реализации очень много. Я просто буду менять Velocity (скорость) Player в Rigibody2D. Нам понадобится немножко C# кода. Правый клик на окошко Assets. Выберите: Create -> C# script. Назовите этот скрипт playerMove. Будьте внимательны с названиями (большие и маленькие буквы различаются).
создание сачка

В окошке Assets будет теперь 2 файла (ну или больше, если используете свои картинки).
создание С# скрипта

Откройте playerMove C# скрипт (двойной клик, или правый клик и выбрать open). Откроется C# редактор. Там будет уже стоять заготовка для вашего скрипта. Выглядит примерно так:
заготовка скрипта

Может быть небольшая разница в стиле, если используется другой редактор. Это не важно.
void Start () {} : эта функция выполняется один раз при старте скрипта. Смотрите Unity Manual для информации.
void Update () {} : эта функция выполняется каждый новый кадр. Смотрите Unity Manual .
void FixedUpdate () {} : выполняется через определенный интервал. Используется в основном для вычислений физики. Стандартный интервал 0.02 сек. Check Unity Manual .
В Юнити есть Input Manager, который помогает контролировать ввод пользователя. Можете посмотреть настройки Input Manager: Edit -> Project Setting -> Input. Потом смотрите на окошко Inspector. Пока ничего не меняйте в нем.
input manager

Input Manager:

Кратко о принципе работы Input Manager. Например: Horizontal ось. Если пользователь нажимает left(левый курсор) или A кнопку, то значение этой оси меняется на -1. Если нажимается right или D кнопка, тогда значение оси будет 1. если эти кнопки не нажаты, то значение будет 0. На самом деле это не совсем точно, значение меняется между -1 and 1. С джойстиком это было бы нагляднее, но клавиатура либо нажата либо нет. И через скрипт мы можем получить значение этой оси из Input Managerа. Смотрите Unity Manual для инфо.
настройки input manager

Теперь мы можем получить три значения из Input Manager (-1 or 0 or 1), в зависимости от нажатых кнопок. И в зависимости от полученного значения из Input Manager мы можем менять velocity (скорость) нашего Player в его Rigidbody2D.

Velocity:

Краткий обзор velocity в Юнити. Velocity это вектор. По значению этого вектора мы видим скорость и направление Rigidbody игрового объекта. Мы можем написать 3Д вектор как (x, y, z). Если объект не двигается, то его velocity равна (0,0,0). Если velocity (-5, 0, 0) то GameObject двигается налево со скоростью 5, с velocity (1, 0, 0) двигается направо со скоростью 1, с velocity (0, 2, 0) двигается наверх со скоростью 2. Юнити это 3Д движок, поэтому не забываем о Z-направлении. Позитивная Z это вперед (в 2Д режиме удаление от нас), негативная Z - приближение. Z-направление не нужно в этом туториале (но не забывайте о Z - оси. Если вы поместите GameObject позади от Camera, то вы не сможете его увидеть в Camera View) при игре. Смотрите Unity Manual для инфо.
векторы в Юнити

Теперь можем сделать C# скрипт для движения. Надеюсь вы знакомы с основой С#.

- Нам нужна float переменная для скорости. Сделайте её public, так у нас будет доступ к ней через Inspector и сможем выставлять её значение не открывая скрипт. Ещё понадобится float переменная значения Horizontal оси. И переменная Vector2 установки скорости и направления движения в Rigibody2D.
public float speed;
float x;
Vector2 move;
- Мы будем изменять velocity в Rigidbody2D. Поэтому нам нужна переменная для компонента Rigidbody2D.
Rigidbody2D rb;
- Теперь мы можем сделать ссылку rb переменной на Rigidbody2D. Это надо будет сделать только один раз. С помощью GetComponent < Name > (); мы получаем доступ к Component от GameObject. Такая ссылка конечно не обязательна, но что бы не писать каждый раз GetComponent < Rigidbody2D > (); когда нам нужен доступ, мы просто заменяем эту команду на линк через переменную rb.
комроненты игрового объекта
void Start () {
rb = GetComponent < Rigidbody2D > ();
}
Для измений в Rigidbody2D лучше использовать FixedUpdate. Так как физика считается через определенные интервалы, то нет смысла менять её каждый кадр. Смотрите Unity Manual для деталей. Мы будем получать значение Horizontal оси на каждом шаге вычисления физики (доступ к Input Manager довольно прост, используйте команду Input.). Потом мы посчитаем вектор направления и скорости в зависимости от значения оси Horizontal и переменной speed (пара слов о rb.velocity.y. мы будем заменять векторную часть скорости по оси-Y (вверх-вниз) на неё же саму при просчете нового вектора rb.velocity. Это делается только для того, что бы исключить наше влияние на движение по Y-оси. Тогда наш сачок сможет например и дальше падать под действием гравитации, хотя мы и будем менять вектор движения по оси-Х. Мы не должны менять этот вектор на (x, 0) или наш сачок Player будет зависать в воздухе при движении налево или направо. В конце мы подменим вектор движения velocity у Player на посчитанный вектор.
void FixedUpdate () {
x = Input.GetAxis ("Horizontal");
move = new Vector2 (x * speed, rb.velocity.y);
rb.velocity = move;
}
В итоге получился такой скрипт:
Забудьте пока о копировании и вставке. Набирайте текст вначале вручную. Будет видно как редактор будет подсказывать возможные варианты при наборе. И пустая функция Update() пока не нужна нам, поэтому я её удалил.
using UnityEngine;
using System.Collections;
public class playerMove : MonoBehaviour {

//видимая из редактора Юнити, float переменная для скорости (лево/право) Player
public float speed;
//переменная для ссылки на компонент Rigibody2D от Player
Rigidbody2D rb;
//float переменная для оси Horizontal из Input Manager
float x;
//Vector2 переменная для просчитанного вектора движения, используется для изменения velocity
Vector2 move;

//функция выполняется 1 раз при старте скрипта
void Start () {
//делаем линк на Rigidbody2D компонент
rb = GetComponent < Rigidbody2D > ();
}

//функция выполняется с определенным интервалом (по умолчанию 0.02)
void FixedUpdate () {
//считываем значение оси из Input Manager и записываем его в переменную
x = Input.GetAxis ("Horizontal");
//высчитываем новый вектор движения (меням х, у оставляем прежней)
move = new Vector2 (x * speed, rb.velocity.y);
//меняем вектор движения
rb.velocity = move;
}
}
Теперь добавьте этот скрипт к Player. Выделите Player в Hierarchy окошке. Кликните на Add Component в Inspector -> Scripts -> Player Move.
(как альтернатива: можете выделить Player в Hierarchy окошке и потом просто перетащить скрипт на окошко Inspector)
добавление скрипта
Выберите Player в Hierarchy, перейдите к Inspector и измените переменную speed в скрипте Player Move на 5 (это скорость движения).
Запустите сцену через Play и попробуйте подвигать сачок с помощью a-d или left - right кнопок. Вернитесь назад в Scene (нажмите Play повторно)

5. Шаг

Нам нужны предметы для поимки. Сделаем сначала один "Good"(хороший) GameObject (игровой объект). Возмите рыбу картинку для этого. Перетащите рыбу картинку в Scene.
- Выделите её в Hierarchy. Измените имя на Fish.
- Перейдите в Inspector и измените Tag на Good (кликните на untagged -> Add New Tag -> Добавьте новый tag Good -> Вернитесь (выберите (если сбросилось выделение) Fish в Hierarchy -> измените untagged на Good. В последствии мы будем использовать этот тэг для проверки соприкосновений.
настройка тега настройка тега настройка тега настройка тега

- Измените Order in Layer на -10. Так этот GameObject будет отрисовываться позади тех, что сейчас находятся в сцене (у нас Ground = 100, Player = 0).
- Добавьте Rigidbody 2D (Add component -> Physics 2D -> Rigidbody 2D). Поставьте Gravity Scale на 0.1. Так уменьшаем скорость падения.
- Поставьте Interpolate на Interpolate (для плавности движения).
- Добавьте Box Collider 2D. Включите галочку Is Trigger.

Collider is Trigger:

Trigger-Collider это похоже на режим призрака для GameObject. Trigger-Collider будет проходить через другие Collider. Но мы сможем регистрировать и обрабатывать эти соприкосновения. Потом мы будем проверять коснулся-ли Player другого падающего объекта (например Fish). Смотрите Unity Manual для деталей.
настройка объекта

В игре мы будем спавнить (это наверно довольно общепринятый сленг, то есть помещать в сцену) эти объекты Fish. Если Fish не был пойман, то этот объект провалится через пол и будет дальше падать. Мы этого не будем видеть, но Юнити продолжит заниматься их вычислением. Поэтому нам лучше удалить эти объекты из сцены. Мы просто можем удалять их по времени (например через 5 секунд). Сделаем небольшой скрипт для этого.
Создайте C# script в Assets (правый клик Assets -> Create -> C# Script). Назовите его timeDestroyer. Откройте его (двойной клик или правый клик и -> Open).
Нам нужна float переменная для продолжительности жизни объекта (public что бы настраивать через Inspector).
public float aliveTimer;
Нам нужна функция удаления GameObject из Scene. GameObject может быть уничтожен с помощью Destroy(gameObject, time); (gameObject это краткая ссылка на тот GameObject, где находится скрипт. Time это задержка в секундах прежде чем GameObject будет уничтожен). Мы можем добавить эту функцию в Start (). Теперь если Fish будет заспавнен, то запустится функция Destroy которая отсчитает заданное время и уничтожит GameObject.
void Start () {
Destroy (gameObject, aliveTimer);
}
Наш скрипт уничтожения получится такой:
using UnityEngine;
using System.Collections;

public class timeDestroyer : MonoBehaviour {

//время жизни объекта
public float aliveTimer;

//исполняется 1 раз при запуске скрипта
void Start () {
//уничтожит текущий объект через заданное время
Destroy (gameObject, aliveTimer);
}
}
Выделите Fish в Hierarchy. Перейдите в Inspector и добавьте timeDestroyer скрипт. Поменяйте Alive Timer на 5.
добавление скрипта

Пока у нас только один объект Fish в Scene. Позже нам понадобится большее количество. Мы можем сделать заготовку для клонирования Fish. В Юнити для этого используется Prefab.

Prefab:

Prefab используется как образец для клонирования. Можно сделать Prefab из любого GameObject. И потом просто использовать клоны по мере необходимости. Prefab не зависит от клонов. Мы можем изменять или уничтожать клоны не портя при этом сам образец. Смотрите Unity Manual для подробностей.
Создать Prefab очень просто. Выберите Fish в Hierarchy и просто перетащите его в Assets. Юнити автоматически создаст Prefab (или правый клик в Assets окошко -> Create -> Prefab, назовите его и перетащите Fish на него).
создание префаба

6. Шаг

Теперь нам нужен Bad (плохой) объект, поимку которого надо избегать. В целом этот объект будет похож на Fish. Только его Tag и картинка будут отличаться (возможно размер коллайдера). Так что просто слегка изменим Fish. Надеюсь вы сделали Prefab от Fish. Выберите Fish в Hierarchie окошке.
- Смените его название на Bomb (правый клик -> Rename)
- Перейдите в Inspector и смените его Tag на Bad (принцип как и с тэгом Good, смотрите шаг 5. untagged -> add new tag -> +)
- Смените картинку на бомбу (выделите Bomb в Hierarchy, перетащите картинку бомбы из окошка Assets в поле Sprite в компоненте Sprite Renderer в Inspector (или нажмите кружок справа от поля Sprite и выберите картинку бомбы)).
- Поправьте размер Collider2D под новую картинку (нажмите Edit Collider в Inspector).
- Сделайте prefab от bomb (выберите Bomb в Hierarchy и перетащите объект в Assets).
создание префаба

После того как сделали Prefab от Bomb, выделите Bomb в Hierarchy и удалите этот объект.

7. Шаг

Теперь сделаем спавнер (есть такое слово ? "рожалку"). Предметы будут спавниться сверху от Camera. Сделаем границы для спавна. Добавьте пустой GameObject. Нажмите кнопку наверху GameObject -> Create -> Empty. У нас появится Empty GameObject в сцене. Выделите этот GameObject и назовите его Spawner (правый-клик -> Rename). Перейдите в Inspector и сделайте ему иконку для лучше видимости в сцене (смотрите скриншот). Измените Z-position на 0 (если отличалось от 0). Выберите moving tool и передвиньте Spawner на левую сторону от камеры Camera. Мы будем использовать эту позицию для границы спавна. Сделайте дубликат от Spawner. Правый клик на него и выберите Duplicate. Передвиньте дубликат на правую сторону. Смените имя на RightSide. Смотрите скриншот для подробностей.
границы спавнера

Теперь можно сделать скрипт для спавна. Создайте новый C# script (правый клик в Assets -> Create -> C# Script) назовите его ItemSpawn. Откройте его. Краткий принцип его работы: у нас будет массив со спавнящимися предметами (пока у нас есть заготовки Fish и Bomb). Периодично мы будем спавнить один случайный предмет из этого массива. Позиция для спавна тоже будет выбранна случайно между границами для спавна. Для границ используем позиции Spawner и RightSide.

Нам нужна переменная для игрового объекта RightSide (мы сможем получить нужную позицию Transform для спавна с этого объекта).
public GameObject RightSide;
Массив для списка падающих предметов. Сделаем его публичным, что бы заполнить через Inspector. Fish и Bomb будут членами этого массива.
public GameObject[] items;
Float переменные для первоначальной задержки спавна и его периодичности.
public float startDelay, repeatRate;
Нам нужна функция для переодичного запуска спавна. Вариантов реализации как обычно много. Я буду использовать функцию InvokeRepeating ("name", startDelay, repeatRate), где name название функции спавна. Эта функция запускается один раз в Start (); и потом она автоматически периодично вызывает функцию спавна.
void Start () {
InvokeRepeating ("Spawn", startDelay, repeatRate);
}
Теперь к функции Spawn. Для начала посчитаем случайную позицию для спавна. Позиция это 3Д вектор. Для Х-части мы возьмем случайное значение между Spawner и RightSide. Для Y-части мы просто возмем Y-значение от Spawner (оно не будет меняться). И Z-значение будет 0.

2Д и Z-ось:

Не забывайте о Z-позиции в 2Д играх. Юнити 3Д движок, если что-то поместите за Camera,то она не сможет отобразить этот объект. По умолчанию Z-позиция у камеры -10.
Vector3 pos = new Vector3 (Random.Range (gameObject.transform.position.x, RightSide.transform.position.x), gameObject.transform.position.y, 0);

Transform:

Небольшое отступление о Transform компоненте. Помните о доступе к компонентам через GetComponent < Name > ();? Transform компонент это исключение. Так как этот компонент в обязательном порядке есть у любого игрового объекта, то есть упрощённый путь доступа к нему. Просто используйте gameObject.transform." и потом уже переходите к его частям .position или .rotation. gameObject указывает на текущий объект (там где скрипт), а transform это прямой доступ к его Transform компоненту.
Теперь у нас есть случайная позиция для спавна. Спавн объекта в Юнити можно сделать через функцию Instantiate (gameobject, position, rotation). Мы выберем случайный объект из массива (item.length это длина массива. Нам не обязательно самим считать его размер. И впоследствии можно будет добавитть новые объекты к массиву без поломки скрипта). Позиция у нас уже высчитана. И ротация будет как у объекта Spawner(то-есть никакой ротации).
Instantiate (items [Random.Range (0, items.Length)], pos, gameObject.transform.rotation);
Скрипт спавна пока получается такой:
using UnityEngine;
using System.Collections;

public class ItemSpawn : MonoBehaviour {

//объект, из которого мы будем считать правую границу спавна
public GameObject RightSide;
//массив с объектами для спавна
public GameObject[] items;
//float переменные: задержка первого спавна и его период
public float startDelay, repeatRate;

//выполняется 1 раз при старте
void Start () {
//запуск периодического выполнения спавна
InvokeRepeating ("Spawn", startDelay, repeatRate);
}

//функция спавна
void Spawn () {
//рандомная X-позиция между Spawn и RightSide
Vector3 pos = new Vector3 (Random.Range (gameObject.transform.position.x, RightSide.transform.position.x), gameObject.transform.position.y, 0);
//спавн случайного предмета на посчитанной позиции
Instantiate (items [Random.Range (0, items.Length)], pos, gameObject.transform.rotation);
}
}
Выделите Spawner в Hierarchy. Добавьте скрипт спавна к нему. Перетащите RightSide из Hierarchy на RightSideполе в скрипте. Разверните массив для предметов (кликните на Items). Заполните его образцами предметов (переташите Fish и Bomb из Assets на Items). Размер массива должен стать 2. Измените delay и rate на 2 каждую (можете настроить потом по желанию).
настройка спавнера

Можете запустить сцену для теста.

8. Step

Теперь нужен скрипт для поимки предметов. С помощью 2Д физики мы можем регистрировать соприкосновения объектов с 2Д коллайдерами. У Bomb и Fish есть Trigger Collider2D. Для регистрации можем использовать OnTriggerEnter2D ().

OnTrigger... вызовы:

OnTriggerEnter2D () - запускается если collider2D попал в триггер
OnTriggerStay2D () - will be started if collider2D находится в триггере несколько кадров
OnTriggerExit2D () - will be started if collider2D вышел из триггера
Смотрите Unity Manual для деталей.
Создайте новый C# script (правый клик в Assets). Назовите его itemChecker. Откройте его.
Нам нужна переменная для учета очков.
public int score;
У OnTriggerEnter2D есть параметр Collider2D. Мы можем проверить какой GameObject попал в триггер. Так есть GameObject, мы можем проверить его Tag. Если это Good предмет, то мы увеличим очки. Если это плохой Bad предмет, то уменьшим их. Потом мы можем уничтожить предмет попавший в сачок.
void OnTriggerEnter2D (Collider2D other) {
if (other.gameObject.tag == "Good") {
score = score + 10;
Destroy (other.gameObject);
}
if (other.gameObject.tag == "Bad") {
score = score - 10;
Destroy (other.gameObject);
}
}
Наш itemChecker скрипт будет такой:
using UnityEngine;
using System.Collections;

public class itemChecker : MonoBehaviour {

//переменная для результата
public int score;

//запустится при попадании объекта с Collider2D в Trigger
void OnTriggerEnter2D (Collider2D other) {
//проверка Tag предмета, это Good ?
if (other.gameObject.tag == "Good") {
//увеличить результат, если да
score = score + 10;
//удалить предмет попавший в триггер
Destroy (other.gameObject);
}
//проверка Tag предмета, это Bad ?
if (other.gameObject.tag == "Bad") {
//уменьшить результат, если да
score = score - 10;
//удалить предмет попавший в триггер
Destroy (other.gameObject);
}
}
}
Выделите Player в Hierarchy. Добавьте itemChecker к нему в Inspector.
добавление скрипта

Сохраните сцену как catchGame. Выделите Player и запустите сцену. Вы должны увидеть как меняется ScoreInspector у Player).

Основа игры готова. Смотрите Вторую часть для продолжения.

готовый проект скачать готовый проект этого туториала.
К сожалению на некоторых версиях Юнити бывает ошибка при импорте проекта. Tag у GameObject может сброситься на undefinied. Придется добавить Bad и Good тэги к падающим объектам (точнее к их префабам). Смотрите 5. и 6. шаги туториала.