Как добавить компонент через скрипт unity
Перейти к содержимому

Как добавить компонент через скрипт unity

Программно привязать/указать/изменить Script в Unity

КАК привязать СКРИПТ к ОБЪЕКТУ на сцене ПРОГРАММНО?

Довольно недавно начал изучать Unity. Всё шло довольно ровно и хорошо, пока не случилось это. Я решил сделать так: (приведена аналогия, чтобы проще было понять):

2) Делаю клон этого кубика по клику кнопки

3) Указать для этого клона другой скрипт (когда создается клон, то скрипт не дублируется)

Запоролся на 3-ем шаге ¯_(ツ)_/¯

1) Куб уже есть на сцене 2) Дублирую с помощью Instantiate(myCube); 3) Кубик от которого создаются копии просто двигается по сцене (WASD), а кубики, которые дублируются меняют цвет/хаотично двигаются/увеличиваются 4) Для каждого созданого кубика действие, которое он будет выполнять задается случайно

Туториал 0: Юнити и C# скрипт — основы

Скажу честно, я не программист, так что вполне возможно будут какие-то неточности. Это не игровой туториал. Я постараюсь рассказать, как работают скрипты в Юнити 3Д.

С# относительно не сложный язык. Точнее сама основа языка простая, сложности начинаются, когда уже совсем далеко углубляешься в него. Но на самом деле с помощью Юнити3Д можно делать простенькие игрушки только используя основы С#. C# объектно ориентированный язык програмирования. Это пишут все, но как я понял большинство не особо понимает смысл этого, как и я. Но учитывая, что придется работать со скриптами, это не так и важно для начала. Не стоит пытаться создать один огромный трудно понимаемый скрипт для всей игры. Пробуйте разделить игру на части. В свою очередь эти части могут взамодействовать друг с другом. Используйте эти части как кирпичи для создания итоговой игры. В C# используется class, который исполняет роль кирпичика. В Юнити довольно просто создать такой class. Создаете новый C# скрипт и называете его по желанию. И, грубо говоря, созданный скрипт и выполняет роль class в Юнити3Д. Далее можно использовать скрипт как компонет для игрового объекта.

Небольшой пример:

Как использовать C# скрипты ?

Не забываем, это не игровой туториал, только вкратце о принципе работы с Юнити3Д.

using UnityEngine;
using System.Collections;

public class Moving : MonoBehaviour <

// Use this for initialisation
void Start () <
>

//Update is called once per frame
void Update () <
>
>

Небольшое объяснение строчек:

Using UnityEngine; Добавляем доступ на UnityEngine библиотеку. Это набор различных классов/функций от Юнити3Д.
using System.Collections; Это стандартная библиотека от Microsoft .NET.
public class Moving : MonoBehaviour < public даёт возможность доступа на этот скрипт с других скриптов. class Moving название нашего скрипта/класса. MonoBehaviour это основной класс от Юнити3Д, в нём такие важные функции как Update(), Start (). Смотрите Unity Documentation для более точного описания.
// Use this for initialization Это просто комментарий. Только для вашего удобства.
void Start () <> void Обозначение, что последующая функция не будет возвращать параметр (то-есть никаких вернувшихся переменных после её вызова не намечается). Start () <> эта функция выполнится один раз при старте скрипта.
void Update () <> Эта функция будет выполняться заново каждый игровой кадр.

Теперь мы можем передвинуть астероид в центр игрового мира (находится на координатах (0, 0, 0)). Позиция игрового объекта определяется в Transform компоненте. Нам надо присоединить наш скрипт к астероиду. С этого скрипта мы можем менять переменные в Transform компонент. Эти переменные и определяют положение объекта в сцене.

Например мы хотим переместить астероид в центр при старте игры.

Если надо получить доступ на какой-то компонент игрового объекта, то обычно надо сделать следующие шаги:

1. Найти нужный игровой объект: Тут много разных вариантов, все зависит от условий.
— Можно использовать поиск из C# скрипта GameObject.Find («Name») / GameObject.FindWithTag («Tag»). Это поиск по имени или тэгу.
— можно создать переменную типа игровой объект public GameObject; и потом в эдиторе указать к какому объекту привязана эта переменная.
— можно получить линк на игровой объект с различных функций. Например: (Trigger, Raycast. ).
— и не нужен поиск объекта, если скрипт уже находится на этом объекте.

2. Получить доступ на компонент этого объекта: через команду gameobject.GetComponent <ComponentName>(); или GetComponent <ComponentName>(); если скрипт на том-же объекте.

Доступ к Transform компоненту:

using UnityEngine;
using System.Collections;

public class Moving : MonoBehaviour <

// Use this for initialisation
void Start () <
//сменить местоположение игрового объекта
transform.position = new Vector3 ( 0 , 0 , 0 );
>

//Update is called once per frame
void Update () <
>
>

Если мы запустим нашу игру, то астероид будет перемещён в центр игрового мира.
Теперь посмотрим на Transform компонент:

Используйте команду transform. для доступа к Transform компоненту на том-же игровом объекте. И в нём можно изменить позицию, вращение и размер игрового объекта (пример: transform.localScale = new Vector3 (0.5F, 1, 1);). Ваш IDE (редактор) будет пытаться помочь в наборе команд и будут показанны различные возможные варианты.

Можно не только изменять переменные, но и просто запросить их значения.

Теперь посмотрим как работать с другими компонентами. У нашего астероида есть компонент для его отрисовки (рендерер).

Например мы хотим зеркально повернуть астероид вдоль y-оси. Так как наш скрипт уже прикреплён к астероиду, то нам не нужен его поиск в игровом мире. Мы можем получить доступ на компонент командой GetComponent <ComponentName>().. Название компонента можно посмотреть в инспекторе игрового объекта (только осторожно с пробелами). C# команда будет:
GetComponent< SpriteRenderer >().flipY = true ;
И скрипт будет:

using UnityEngine;
using System.Collections;

public class Moving : MonoBehaviour <

// Use this for initialisation
void Start () <
//сменить местоположение игрового оьъекта
transform.position = new Vector3 ( 0 , 0 , 0 );
//доступ к компоненту отрисовки и сменить переменную, отвечающую за зеркальное отображение по оси Y
GetComponent< SpriteRenderer >().flipY = true ;
>

//Update is called once per frame
void Update () <
>
>

using UnityEngine;
using System.Collections;

public class Moving : MonoBehaviour <

//декларация ссылочной переменной для компонента отрисовки спрайтов
SpriteRenderer sr;

// Use this for initialisation
void Start () <
//сменить местоположение игрового оьъекта
transform.position = new Vector3 ( 0 , 0 , 0 );
//делаем ссылку на компонент
sr = GetComponent< SpriteRenderer >();
//меняем переменную, отвечающую за зеркальное отображение по оси Y
sr.flipY = true ;
>

//Update is called once per frame
void Update () <
>
>

Похожим образом мы можем получить и доступ к компонентам на других игровых объектах.
Для начала нам надо «найти» другой игровой объект. Как я уже и писал, тут довольно много различных вариантов в зависимости от ситуации. Например в сцене есть другой игровой объект. Его имя Ship и тэг Player (Tag используется для идентификации объектов (похоже на имя, только скорость обработки быстрее)).

1. Если игровой объект находится в сцене с самого начала и не пропадает до запроса к нему, то мы можем создать открытую ссылочную переменную playerShip (с тимпом GameObject) в нашем скрипте и добавить этот объект в эту переменную через инспектор (просто перетащить объект на переменную в редакторе). И тогда через эту переменную у нас будет доступ на игровой объект. Например мы хотим поместить корабль на позицию (1, 1, 0) при старте игры. C# строчка будет:
playerShip.transform.position = new Vector3 ( 1 , 1 , 0 );

using UnityEngine;
using System.Collections;

public class Moving : MonoBehaviour <

//декларация ссылочной переменной для компонента отрисовки спрайтов
SpriteRenderer sr;
//публичная ссылочная переменная для корабля игрока
public GameObject playerShip;

// Use this for initialisation
void Start () <
//сменить местоположение игрового оьъекта
transform.position = new Vector3 ( 0 , 0 , 0 );
//делаем ссылку на компонент
sr = GetComponent< SpriteRenderer >();
//меняем переменную, отвечающую за зеркальное отображение по оси Y
sr.flipY = true ;
//получаем доступ к transform компоненту игрока и меняем его местоположение
playerShip.transform.position = new Vector3 ( 1 , 1 , 0 );
>

//Update is called once per frame
void Update () <
>
>

2. Мы можем найти игровой объект в сцене через поиск и сделать на него ссылку через скрипт с помощью команды GameObject.Find («Name») or GameObject.FindWithTag («Tag»). Поиск по тэгу производится быстрее чем по имени. C# строчка будет:
playerShip = GameObject .Find( «Ship» );
или:
playerShip = GameObject .FindWithTag( «Player» );

using UnityEngine;
using System.Collections;

public class Moving : MonoBehaviour <

//декларация ссылочной переменной для компонента отрисовки спрайтов
SpriteRenderer sr;
//публичная ссылочная переменная для корабля игрока
public GameObject playerShip;

// Use this for initialisation
void Start () <
//сменить местоположение игрового оьъекта
transform.position = new Vector3 ( 0 , 0 , 0 );
//делаем ссылку на компонент
sr = GetComponent< SpriteRenderer >();
//меняем переменную, отвечающую за зеркальное отображение по оси Y
sr.flipY = true ;
//ищем в сцене корабль игрока и делаем ссылку на него
playerShip = GameObject .FindWithTag( «Player» );
//получаем доступ к transform компоненту игрока и меняем его местоположение
playerShip.transform.position = new Vector3 ( 1 , 1 , 0 );
>

//Update is called once per frame
void Update () <
>
>

using UnityEngine;
using System.Collections;

public class Moving : MonoBehaviour <

//декларация ссылочной переменной для компонента отрисовки спрайтов
SpriteRenderer sr;
//публичная ссылочная переменная для корабля игрока
public GameObject playerShip;

// Use this for initialisation
void Start () <
//сменить местоположение игрового объекта
transform.position = new Vector3 ( 0 , 0 , 0 );
//делаем ссылку на компонент
sr = GetComponent< SpriteRenderer >();
//меняем переменную, отвечающую за зеркальное отображение по оси Y
sr.flipY = true ;
//ищем в сцене корабль игрока и делаем ссылку на него
playerShip = GameObject .FindWithTag( «Player» );
//получаем доступ к transform компоненту игрока и меняем его местоположение
playerShip.transform.position = new Vector3 ( 1 , 1 , 0 );
//указываем, что работаем с кораблем игрока, получаем доступ к компоненту отрисовки и зеркально отображаем по оси Х
playerShip.GetComponent < SpriteRenderer > ().flipX = true ;
>

//Update is called once per frame
void Update () <
>
>

3. Мы можем получть объект с различных игровых функций. Я покажу некотрые из них в последующих туториалах (как пример: OnTriggerEnter2D (Collider2D otherCollider) <> Ссылка на объект попавший в триггер будет в otherCollider переменной).

Наверняка уже заметили, что создание игры в Юнити — это просто работа с переменными в компонентах игровых объектов (я сейчас не говорю о создании музыки, моделей, текстов . Это уже совсем другая история). Теперь посмотрим на основы С# скриптов. Описание будет довольно коротким и затронет только базовые части. Так что для подробностей придется немножко погуглить или побродить по форумам.

Основы С# скриптов:

1. Переменные:

2. Ссылочные переменные классов:

Spoiler GameObject:
Все объекты в сцене Юнити это игровые объекты. Поэтому GameObject как базовый класс используется довольно часто. Как и большинство классов содержит в себе не только различные переменные, но и функции. Смотрите Unity Documentation для более точного описания. GameObject player;
//поиск оьъекта с тэгом Enemy и создание переменной с ссылкой на него
GameObject enemy = GameObject .FindWithTag ( «Enemy» );
Transform:
Один из очень часто используемых компонентов. Этот компонент есть у любого игрового объекта в Юнити. Отвечает за местоположение и размеры объекта в игровом мире. Так как в Юнити есть упрощённый доступ к компонету Transform у игрового объекта через команду gameobject.transform. , то используется как ссылочная переменная не так уж и часто. Смотрите Unity Documentation для более точного описания. Transform enemyPosition;
//считывание координаты х из трансформ компонента
float x = enemyPosition.position.x;
Sprite:
Класс представляющий 2Д картинку (спрайт) в качестве рессурса в Юнити. Если вы импортируете спрайт в Юнити, то будет автоматически создан новый класс содержащий этот спрайт с его различными настройками. В качестве ссылочной переменной понадобится при работе с компонентом отрисовки спрайтов. Смотрите Unity Documentation для более точного описания. Sprite enemyBullet;
SpriteRenderer:
Класс отвечающий за отрисовку (рендеринг) спрайта на экране. Рессурс для отрисовки берется из Sprite (см. выше). Как и большинство компонентов содержит в себе различные переменные и функции. Смотрите Unity Documentation для более точного описания. SpriteRenderer sr;
//активация переменной, отвечающей за зеркальное отображение по оси Y
GetComponent< SpriteRenderer >().flipY = true ;
С# скрипты и другие компоненты:
Как я уже говорил, ваши скрипты являются компонентами в Юнити. Поэтому ссылочные переменные работают аналогичным образом.
1. создаёте переменную по типу компонента (используйте его название).
2. получаете доступ к компоненту через ссылочную переменную: variable = GetComponent <ComponentName>();

В качестве примера скрипт из вступления: Moving moving;
moving = GetComponent< Moving >();
moving.playerShip.transform.position = new Vector3 ( 1 , 1 , 0 );
Все остальные компоненты работают аналогично. Не стану их описывать, так как их просто огромное количество.

3. Массивы (статические и динамические):

4. Модификаторы доступа:

5. Области видимости(действия) переменных:

Spoiler глобально в классе:
Переменная декларированная в классе, но не входящая в функции этого класса может быть использована глобально всеми функциями этого класса.
локально в функции:
Переменная декларированная в функции, может быть использована только в этой функции.
локально в цикле:
Область видимости такой переменной ещё меньше, она используется только локально в пределах цикла. using UnityEngine;
using System.Collections;

public class Moving : MonoBehaviour <

//переменная speed может быть использованна любой функцией этого класса
public int speed;

void RandomFunction () <
//переменная isMoving может быть использованна только в пределах RandomFunction () <. >
bool isMoving = true;
//переменная i может быть использованна только в пределах цикла
for ( int i = speed; i < 0 ; i—) <
speed = i;
>
isMoving = false;
>
>

6: Арифметические операторы:

7. Математические функции:

8. Условия и логические операторы:

Spoiler логические операторы сравнения:
Результат сравнения это бинарный результат, то есть ложно или истинно (true/false). Возможны следующие сравнения:
== — равно
!= — не равно
> — больше
< — меньше
>= — больше или равно
<= — меньше или равно

условные операторы:
Условные операторы позволяют провести сравнение и выполнить определенную часть кода в зависимости от результата.
if . else:
Краткая форма этого условного оператора состоит только из условия и выполняемой части кода, если условие истинно. if (hp <= 0 ) <
isDead = true ;
canFight = false ;
> Полная форма состоит из условия, выполняемой части кода, если условие истинно и выполняемой части кода, если условие ложно. if (hp <= 0 ) <
isDead = true ;
canFight = false ;
> else <
isDead = false ;
canFight = true ;
> Возможно объединение различных условий в одну конструкцию. if (hp <= 0 ) <
isDead = true ;
canFight = false ;
> else if (hp == 100 ) <
isDamaged = false ;
> бинарные логические операторы:
С помощью таких операторов можно создавать более сложные условия, состоящих из нескольких подусловий.
&& — логическое И . Будет истинно, если оба условия истинны. Или ложно, если оба или одно из них ложно.
|| — логическое ИЛИ . Будет истинно, если одно из условий истинно. И ложно, если оба условия ложны.
if (hp < 0 || hp > 0 ) <
isZero = false ;
> else <
isZero = true ;
> switch:
Этот логический оператор используется для обработки множества вариантов при нахождении истинного значения. string direction = «left» ;

//искомое выражение
switch (direction) <
//возможный вариант, если совпадает, то выполняется последующий код
case ( «up» ):
move = Vector2 .up;
isMoving = true ;
//прерывает дальнейшее выполнение логического оператора (при совпадении варианта)
break ;
//возможный вариант, если совпадает, то выполняется последующий код
case ( «down» ):
move = Vector2 .down;
isMoving = true ;
//прерывает дальнейшее выполнение логического оператора (при совпадении варианта)
break ;
//в данном примере выполнится эта часть кода и работа логического оператора будет завершена
case ( «left» ):
move = Vector2 .left;
isMoving = true ;
//прерывает дальнейшее выполнение логического оператора (при совпадении варианта)
break ;
//возможный вариант, если совпадает, то выполняется последующий код
case ( «right» ):
move = Vector2 .down;
isMoving = true ;
//прерывает дальнейшее выполнение логического оператора (при совпадении варианта)
break ;
//если ни один из вариантов не был истинной, то выполняется часть кода стоящая после default
default :
move = Vector2 .zero;
isMoving = false ;
//прерывает дальнейшее выполнение логического оператора
break ;
>

9. Циклы:

Spoiler for:
Этот цикл выполняется определённое количество раз. //для примера, декларация массива на 10 целых элементов
public int [] numbers = new int [ 10 ];

//int i = 0; декларация с инициализацией счетчика цикла
//i < 10; проверка возможности запуска следующего цикла (пока условие истинно)
//i++; изменение счетчика цикла
for ( int i = 0 ; i < 10 ; i++) <
//исполняемая часть кода при каждом новом цикле
//в данном примере, заполнение массива числами от 0 до 9
numbers [i] = i;
> Хоть это и не обязательно, но советую использовать в счетчиках циклов целые значения, чтобы избежать ошибок от дробных вычислений.

while:
Этот цикл выполняется пока условие истинно. //для примера, декларация массива на 10 целых элементов
public int [] numbers = new int [ 10 ];
//декларация с инициализацией переменной к, которую будем использовать для проверки условия цикла
int k = 9 ;

//проверка условия цикла, выполнить цикл, если условие истинно
while (k >= 0 ) <
//выполняемый фрагмент кода в фигурных скобках
//заполнение массива числами от 9 до 0 в обратном порядке
numbers [k] = k; //уменьшение переменной на 1 (чтобы получить ложное условие)
k—;
> Будьте осторожны с циклами, чтобы не получить «вечный» цикл, когда условие всегда истинно и цикл повторяется вечно.

do. while:
Отличие этого цикла от цикла while только в том, что проверка условия производится после выполнения фрагмента кода. Поэтому этот цикл выполнится всегда как минимум один раз. //декларация публичной текстовой переменной
public string testText;
//декларация и инициализация целой переменной, для условия цикла
int j = 0 ;

//выполнение фрагмента кода цикла
do <
//добавление к текстовой переменной цифры преобразованной в текстовый символ
testText = testText + j.ToString();
//увеличение j на единицу
j ++;
//проверка условия, повторить цикл, если условие истинно
> while (j < 10 );
//результат работы цикла это текст «0123456789»
foreach:
Цикл для работы с массивами. Перебирает все элементы по одному. //декларация и инициализация массива
int [] numbers = new int [ 5 ] < 21 , 28 , 13 , 4 , 15 >;
//декларация массива для копирования
int [] numbersCopy = new int [ 5 ];

//вспомогательная переменная для индекса массива
int i = 0 ;
//запуск цикла проходяшего по всем элементам массива
//переменная number должна совпадать с типом элементов массива
foreach ( int number in numbers) <
//копирование текущего элемента в другой массив
numbersCopy [i] = number;
//увеличение индекса на 1, для доступа к следующему элементу в массиве для копии
i++;
>
//итог цикла это копирование элементов в новый массив
операторы break и continue:
Эти операторы помогают управлять исполнением циклов.
break — этот оператор полностью прекращает цикл и переходит к дальнейшему исполнению программы
continue — этот оператор прекращает текущее исполнение цикла и начинает новое
//вспомогательная переменная для индекса массива
int i = 0 ;
//запуск цикла проходяшего по всем элементам массива
//переменная number должна совпадать с типом элементов массива
foreach ( int number in numbers) <
//копирование текущего элемента в другой массив
numbersCopy [i] = number;
//увеличение индекса на 1, для доступа к следующему элементу в массиве для копии
i++;
//как переменная для индекса стала равна 3, прекращаем исполнение цикла
if (i == 3 )
break ;
>

10. Функции:

Spoiler стандартные функции от Юнити:
Существует много различных функций в Юнити. Тут я точно не смогу показать и малой части. Поэтому пока ограничимся несколькими примерами. В дальнейшем в туториалах будут попадаться и новые функции.

Instantiate:
Эта функция помещает клон объекта в сцену. Обычно используется для клонирования префаба(образца). //создаёт клон префаба в сцене на заданной позиции (Vector3) с заданным вращением (Quaternion)
Instantiate (prefab, position, rotation); Destroy:
Эта функция удаляет объект из сцены. //удаляет игровой объект из сцены после заданного интервала (или сразу, если время не указать)
Destroy (gameobject, time); функции классов:
Часто, если используете какой-то компонент (класс), то он содержит различные функции для работы с ним. Список этих функций можно увидеть в редакторе C# после набора ссылочной переменной (+ точка) указывающей на этот компонент. //изменяет дробную переменную в компоненте аниматор
GetComponent < Animator > ().SetFloat ( «Speed» , 0 );
функции пользователя:
Конечно можно использовать и свои функции для выполнения нужных задач. //функция нанесения повреждений
public void DoDamage ( int damage) <
hp = hp — damage;
if (hp <= 0 )
Destroy (gameObject);
>

Разница между 2D и 3D

Unity поддерживает разработку 2D-игр, и для удобства процесса разработки перед созданием нового проекта он может быть определен как 2D.

Picture1

Переключение режима разработки в уже созданном проекте осуществляется через меню Edit – ProjectSettings–Editor–DefaultBehaviorMode–Mode.

Picture2

В 2D-режиме Unity вносит некоторые изменения в настройки редактора:

  • Окно сцены по умолчанию включено в 2D-режиме (если необходимо, данная настройка легко переключается обратно в 3D-режим с помощью переключателя в верхней части окна сцены). Эта настройка независима от остальных настроек 2D-режима и может быть изменена в любое время.
  • Свойство «Projection» камеры по умолчанию установлено в «Orthographic», а «Size» равно.
  • При импорте новых изображении их Texture Type по умолчанию установлен в «Sprite (2D\uGUI)».

Компоненты 2D-объектов

Рассмотрим некоторые компоненты и события 2D-объектов и их отличия от компонентов и событий,использующихся для 3D-объектов.

Компоненты

BoxCollider2D –это прямоугольный коллайдер, используемый при работе с 2D физикой.

Picture3

2D коллайдер/триггер обрабатывает события (сталкивание, пересечение и т.д.) независимо от того, где он располагается по координате Z. Все свойства коллайдера точно такие же, как и у BoxCollider, за исключением одного. Переключатель Used By Effector отвечает за то, используется ли данный коллайдер прикрепленным компонентом – Effector 2D (данные компонент бывает разного типа: точка, область, платформа и т.д.).

  • Material – физический материал, который определяет свойства столкновений, такие как трение и отскок.
  • IsTrigger – является ли коллайдер триггером?
  • Used by Effector – используется ли данный коллайдер прикрепленным компонентом – Effector.
  • Auto Tiling – установите этот флажок, если компонент Sprite Renderer установлен в режим Tile. Это позволит автоматически, обновлять форму коллайдера, которая будет корректироваться по форме спрайта.
  • Offset – локальное смещение геометрии коллайдера.
  • Size – ширина и высота прямоугольника в единицах локального пространства.
  • Edge Radius – смягчает грани, делая коллайдер более круглым, по умолчанию значение равно
  • Info – общая информация о состоянии коллайдера.

Визуальное отображение пустых объектов с 2D- и 3D-коллайдерами при включении 3D-режима в окне сцены:

Picture4

Rigidbody2D – компонент помещает объект под контроль физического движка. В целом компонент похож на Rigidbody, но объект может двигаться только в плоскость XY, а вращаться только перпендикулярно этой плоскости.

Picture5

  • UseAutoMass – рассчитать массу автоматически,исходя из коллайдера;
  • GravityScale – как гравитация воздействует на объект;
  • Sleeping Mode – режим, когда объект выключается из физической симуляции (в целях оптимизации).
  • Never Sleep – всегда активен (необходимо стараться избегать данного режима);
  • Start Awake – активен при запуске (режим включен по умолчанию);
  • Start Asleep – не активен при запуске, но может быть разбужен (столкновением или через скрипт).

Спрайты

Настройки спрайта (Import Settings)

После импорта изображения в проект в 2D-режиме разработки его настройки по умолчанию выглядят следующим образом:

Picture6

  • В верхней части находится иконка – превью спрайта (также превью находится в нижней части инспектора), отображается название файла, кнопка Open, которая открывает изображение в программе просмотра изображений, установленной в системе по умолчанию.
  • Texture Type – устанавливает базовые параметры в зависимости от предназначения текстуры(изображения).
  • Sprite Mode – устанавливает, в каком режиме спрайт будет извлекаться из изображения, как один спрайт (Single) или как несколько раздельных спрайтов (Multiple). Второй режим может использоваться для импорта спрайтов как кадров анимации, а также как несколько спрайтов, относящихся к одному объекту. Третий режим Polygon позволяет настраивать форму, размер и pivot point для вашего спрайта.
  • PackingTag – имя атласа, в который данное изображение должно быть запаковано.
  • Pixels Per Unit – количество пикселей в изображении спрайта, которые соответствуют одному юниту (внутренняя единица измерения в Unity).

Компонент Sprite Renderer

Данный компонент позволяет отображать спрайты и используется как в 2D, так и в3D-сценах.

Picture7

Компонент имеет следующие свойства:

  • Sprite – спрайт.
  • Color – цвет.
  • Flip – отражение спрайта по оси X или Y.
  • Material – материал, стандартные шейдеры, которые используют для материала спрайта – Sprites/Default (не взаимодействует с освещением на сцене), Sprites/Diffuse (взаимодействует с освещением на сцене).
  • Draw Mode – выберите параметр из списка Draw Mode, чтобы определить, как масштабируется спрайт при изменении его параметров.
  • Simple – это значение по умолчанию. Изображение изменяется во всех направлениях,когда его размеры меняются.
  • Sliced – применяйте это, если хотите нарезать спрайт на 9 частей, чтобы эти части можно было растягивать. В этом режиме углы остаются одинаковыми, верхняя и нижняя часть тянутся в собственную высоту, а центр тянется в ширину и высоту.
  • Size – используйте это значение, чтобы изменить горизонтальный и вертикальный размер спрайта. Если вы хотите, чтобы slice работала корректно, вам нужно настроить это значение. Компонент Transform применяется только по умолчанию.
  • Tiled – применяйте это если хотите нарезать спрайт на 9 частей, чтобы эти части можно было повторять. В этом режиме углы остаются одинаковыми, верхняя и нижняя часть тянутся в собственную высоту, а центр тянется в ширину и высоту.

Sprite Creator

С помощью этого инструмента можно создавать временные заменители спрайтов. Их можно использовать в проекте в процессе разработки, а затем, когда будет создана необходимая графика, заменить. Для создания таких спрайтов необходимо выбрать меню Assets – Create – Sprites, далее один из доступных типов спрайтов: Square, Triangle, Diamond, Hexagon, Circle, Polygon.

Через меню Assets – Create создаются не объекты, а ассеты, поэтому после создания спрайта в папке проекта появляется новый ассет, а на сцене ничего не изменяется. Далее необходимо добавить созданный спрайт на сцену.

Спрайты в окне проекта:

Picture8

Спрайты на сцене:

Picture9

При создании спрайта Polygon открывается Sprite Editor, где можно изменить форму спрайта и некоторые его параметры. Далее более подробно об этом редакторе.

Sprite Editor

Чаще всего спрайт – это одно изображение, но иногда спрайт содержит несколько элементов, которые каким-либо образом связаны друг с другом и объединены в одно изображение. Для работы с такими спрайтами в Unity есть специальный редактор.

Если для спрайта установлен режиме Sprite Mode – Single, часть функций редактора недоступна, и он выглядит следующим образом:

Picture10

В режиме SpriteMode – Multiple:

Picture12Picture11

SpritePacker

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

Необходимо указывать Packing Tag в настройках текстуры, чтобы включить упаковку спрайтов для данной текстуры.

По умолчанию упаковщик спрайтов отключён, но его работу можно настроить через настройки редактора Edit->Project Settings->Editor. Метод упаковывания спрайтов можно установить в состояние Enabled for Builds (упаковывание будет работать для сборок, но не в режиме Play) или в состояние Always Enabled (упаковывание будет работать и во время сборки и в режиме Play).

Указав для нескольких текстур (спрайтов) одинаковый Packing Tag, можно открыть Windows – SpritePacker, нажать кнопку Pack и посмотреть расположение текстур в атласе.

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

Инструменты в верхней части окна упаковщика спрайтов:

  • Pack – инициализирует операцию упаковывания.
  • Repack – переупаковка атласа (обновление).
  • View Atlas – атлас, который необходимо отобразить в окне (если при максимальном размере текстуры в неё не помещаются все спрайты, атлас может быть разбит на множество страниц).
  • Page – позволят выбрать страницу атласа, которую необходимо отобразить в окне.
  • Меню, следующее за номером страницы – выбор правил упаковывания использующиеся для текущего атласа.

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

Атласы кешируются в Project\Library\AtlasCache. Удаление этой папки и последующий запуск Unity приведёт к принудительной перепаковке всех атласов. Во время удаления Unity необходимо закрыть. Максимальный размер атласа по умолчанию равен 2048х2048. При назначенном свойстве PackingTag текстуры не будут сжиматься, чтобы упаковщик спрайтов мог использовать оригинальные значения пикселей при сжатии атласов.

Понятие FPS

FPS – аббревиатура от Frames Per Second, что в переводе на русский означает количество кадров в секунду. Видео – это процесс смены статических кадров. Каждый кадр – это статическое изображение. Количество кадров в секунду – это скорость смены изображений.

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

Человеческий глаз способен воспринимать смену картинок, как видео при смене не менее 25-30 кадров в секунду.

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

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

Picture13

Основные методы класса MonoBehaviour

MonoBehaviour – класс, на базе которого (наследуются) по умолчанию создаются все скрипты в Unity. Скрипты создаются через контекстное меню в окне проекта, через меню Component на верхней панели инструментов, при помощи кнопки Add Component в окне инспектора (когда выделен какой-либо объект). Скрипт работает только тогда, когда он является компонентом объекта на сцене, причём некоторые функции (методы) скрипта могут срабатывать даже тогда, когда сам скрипт выключен(неактивен).

Для редактирования скрипта после его создания необходимо дважды нажать на него ЛКМ в окне инспектора или в окне проекта. Скрипт откроется в той среде разработки, которая указана в настройках Editor–>Preferences–>External Tools–>External Script Editor (обычно это Visual Studio или MonoDevelop). Там же можно сменить среду разработки.

Имя класса в скрипте должно совпадать с именем файла (это происходит автоматически, при создании файла). По умолчанию в скрипте создаются две функции (метода) – Start() и Update(), но существуют и другие функций, которые могут быть использованы как унаследованные от MonoBehaviour. Так же можно создавать свои функции.

По умолчанию скрипт выглядит следующим образом:

Awake()

Функция, которая вызывается один раз при запуске игры до функции Start(). Вызывается в случайном порядке среди объектов на сцене, для которых она реализована. Функция срабатывает даже тогда, когда скрипт не активен.

Start()

Функция, которая также вызывается один раз, но в тот момент, когда скрипт становится активным. Вызывается перед функций FixedUpdate(),Update()ит.д.

FixedUpdate()

Функция, которая выполняется каждый фиксированный отрезок времени. Можно настроить в Edit–>Project Settings–>Time – Fixed Time step. Используется для обработки физики (приложения силы, импульса к объект у и т.д.)

Update()

Функция, которая выполняется каждый кадр. Используется для обработки игровой логики.

Для того, чтобы реализовать выполнения какой-либо действия с определенной частотой, например, раз в секунду,используют Time.deltaTime * 1 .

deltaTime – время (в секундах), прошедшее с последнего кадра. Это значением позволяет сделать игру независимой от скорости смены кадров.

LateUpdate()

Функция, которая выполняется каждый кадр. Вызывается после того, как все Update() функции будут вызваны. Используется для того, чтобы упорядочить выполнения действий в скрипте. Например, если камера следует за объектом, движение которого реализовано в Update() функции.

Практика

Рассмотрим проект на примере 2D Platformer’a от UnityTech.

Picture14

Давайте разберем, из чего состоит основа геймплея 2DPlatformer’a.

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

Picture15

Picture16

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

Аниматор — позволит нам анимировать нашего героя.

Picture17

Rigidbody позволит физически взаимодействовать с препятствиями, а чтобы мы не проваливались под пол и фиксировать столкновения с препятствиями, нам понадобится Box Collider2D.

Picture18

Picture19

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

Picture20

На основной демонстрационной сцене есть куча разных объектов, которые могут нам пригодиться для создания своей игры, их можно найти, если вы выберете нужный объект и найдёте на компоненте sprite renderer поле sprite, кликнув на него, редактор покажет, где у вас в проекте лежит данный объект.

Picture21

Теперь можно расставлять объекты на сцене, просто перетаскивая их из окна Project. Буквально за несколько движений мы с вами уже сделали свой уровень с персонажем.

Picture22

Главное, не забыть положить нашему персонажу объект groundCheck в иерархии, как дочерний, чтобы мы могли прыгать и указать всем балкам, что они лежать на слое Ground, не забывая о коллайдерах.

Практическое задание

** Проект 1 (Используя готовый проект собрать свой игровой уровень)

  • Скачать несколько бесплатных ассетов и собрать свой уровень.
  • Заменить спрайт персонажа на свой.
  • Собрать свою сцену на основе 2D-платформера, чтобы противники спаунились и их можно было убивать.

Проект 2 (Используя графику, анимации, звуки реализовать простейший раннер)

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

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *