C# — Обращение к свойству компонента объекта в Unity3D


Содержание

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

Вступление:

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

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

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

Как использовать 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 (); или GetComponent (); если скрипт на том-же объекте.

Доступ к 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 ().. Название компонента можно посмотреть в инспекторе игрового объекта (только осторожно с пробелами). 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 ();

В качестве примера скрипт из вступления: 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
//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);
>

Скрипты в Unity3D. Урок 0. Основы

Два основных компонента у объекта в Unity3D — это Transform и GameObject.


GameObject

GameObject — основа, контейнер, который содержит в себе все компоненты любой объект в Unity3D. Чтобы удалить, к примеру, игровой объект — удалять нужно именно GameObject этого объекта. Для доступа к GameObject — используется переменная, которая присутствует по умолчанию в любом скрипте, унаследованном от MonoBehaviour (то есть в любом скрипте, созданном через Unity3D).

Получение ссылки на игровой объект

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

Уничтожение игрового объекта

Данным способом можно удалить игровой объект.

Активация/деактивация игрового объекта

Деактивация объекта аналогична снятия галочки инспекторе Unity3D, которая обведена красным цветом на скриншоте ниже.

Деактивация элемента деактивирует также все его дочерние объекты и останавливает выполнение в их скриптов.

Добавление новых компонентов и скриптов игровому объекту

Таким образом можно добавить абсолютно любой компонент, либо скрипт, который можно добавить в редакторе Unity3D.

Получение доступа к компоненту игрового объекта

Таким же образом можно получить доступ к любому компоненту игрового объекта.

Переименование игрового объекта. Считывание имени объекта

Сделать объект статичным

Данный код аналогичен установке/снятию галочки в редакторе Unity3D (на скрине ниже).

Установить слои игровому объекту, а также считать их

Установить тэг игровому объекту, а также его считывание

Transform

С трансформом всё немного проще — этот компонент не является основой, но тем не менее — является основной и, главное, неотъемлемой частью GameObject’а. Он отвечает за месторасположение объекта на сцене, его «вращении», размерах, а также содержит информацию о дочерних и родительском объектах.

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

Изменение положение объекта

За положение объекта на сцене отвечает элементы transform.position и transform.localPosition.

Они оба являются переменной типа Vector3 и имеют в себе 3 главных составляющих x,y и z, которые соответствуют координатам в трехмерном пространстве. Следует учитывать, что x, y и z невозможно менять напрямую — они только для чтения. Чтобы добавить единичку к x — нужно добавить к самому transform.position новый Vector3, который равен (1,0,0), что добавить к x единицу, а к y и z — нули.

Чем же отличаются transform.position и transform.localPosition?

Их главное (и единственное отличие) заключается в том, что position — показывает и принимает координаты объекта, относительно мировых координат, а localPosition — относительно родительского объекта. Если же игровой объект является «корневым», то есть у него нет родительских объектов, то position и localPosition будут равны.

Движение объекта

Сначала рассмотрим элементарные варианты.

Как мы уже говорили — position (буду далее использовать именно его, так как отличия от localPosition только в том, относительно чего эти координаты) является переменной типа Vector3. Поэтому для его изменения нужно либо прибавить к нему другой вектор, либо вычесть другой вектор, либо заменить его другим вектором.

Рекомендуется использовать функцию transform.Translate.

Это уже не переменная, как transform.position — это функция. У неё есть два входящих параметра:

  1. Vector3, который отвечает за то, в каком направлении будет двигаться объект;
  2. Space.Self/Space.World — то, относительно чего будет двигаться игровой объект. Space.Self — аналогичен transform.localPosition, а Space.World — аналогичен transform.position.

Вращение объекта

За вращение объекта отвечает компонент transform.rotation, transform.localRotation и функция transform.Rotate.

Здесь все аналогично transform.position. Кроме одного, несмотря на то, что в редакторе Unity3D Rotation представляет собой Vector3, то есть вращение относительно оси X, оси Y, оси Z. Но в коде оно представлено в виде кватернионов. Что такое кватернион — отдельная история. И обычно её изучают в вузах. По факту — знание кватернионов не обязательно для разработки игр. К счастью разработчики Unity3D это понимают и сделали две удобные для программистов вещи:

  1. Функция transform.Rotate(Vector3 vector, Space.World(либо Self));
  2. Функция Quaternion.Euler(float x,float y,float z), которая как раз возвращает кватернион;

Меньше слов — больше кода:

Вместо rotation можно применять localRotation, аналогично position.

Такой подход аналогичен transform.Translate и также является более производительным.

Поиск других объектов на сцене


Есть два подхода поиска объекта на сцене.

  1. GameObject.Find(«имяОбъекта»); Он же «пушка по воробьям». Несмотря на кажущуюся скорость — метод является достаточно прожорливым и при частом использовании на большой сцене может стать большой проблемой. Однако он же самый простой способ (хотя и ненадежный). А ненадежный он потому, что редактор Unity3D позволяет давать одинаковые имена объектам. А GameObject.Find возвращает только один элемент, который он найдет первым.
  2. transform.FindChild(«имяДочернегоОбъекта») — функция возвращает переменную типа transform нужного объекта. Для доступа к GameObject этого объекта особых усилий прилагать не нужно, так как ссылка на него уже содержится в transform (как и ссылка на transform содержится в GameObject’е).

Также можно запрашивать дочерние элементы по их номеру:

Также дочерний элемент может запросить родительский, а также родительский родительского и так далее:

В следующих статьях будет информация о том, что такое private, public, static, отправление сообщений игровым объектам.

12 комментариев для “Скрипты в Unity3D. Урок 0. Основы”

Отличный урок! Планируется ли продолжение?

Здравствуйте! Да, продолжение планируется и уже есть заготовки, но времени, увы, нет совсем =(

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

var objectBoxColl > ещё бы растолковать,нубу ,почему, где, и в каком случае слова пишутся с маленькой и большой буквы.
Типа — функции с маленькой, переменные с большой.
Почему object с маленькой а BoxCollider c большой.
И краткие примеры, как эти коды можно в коде применять..
//и кто такой «anotherTransformLink»
var anotherTransformLink = childGameObject.transform;

И коментарии бы типа:
var childTransform = transform.FindChild(«myChild1»); // находим myChild1 помещаем в childTransform
var childGameObject = childTransform.gameObject; // тут что происходит я хрен чё понимаю откуда что берётся
var anotherTransformLink = childGameObject.transform; // и зачем столько букав

А так-то нормуль, есть что законспектировать.

Здравствуйте! Спасибо за советы, я обязательно их учту при написании следующих статей.
Постараюсь вкратце ответить на ваши вопросы.
1) Слова в коде относятся к командам, классам, интерфейсам, или именам переменных. Обычно в C# с большой буквы пишется класс, интерфейс, или переменная с модификатором доступа ‘public’ (не забываем про функции). Где, как и в каких случаях что используется тяжело описать, так как это основы языка программирования C#.
Например:
var myObject = new MyObject().
Конкретно в данном случае — MyObject — это класс. А myObject — это конкретный экземпляр класса MyObject.

А вот другой пример:
public GameObject MyGameObject;
Это публичное свойство класса типа GameObject. Сам экземпляр данного класса называется MyGameObject и может быть доступен как и изнутри самого класса, так и из других классов, у которых есть ссылка на данный экземпляр класса.

2) Почему objectBoxCollider с маленькой, а BoxCollider с большой? ObjectBoxCollider — это имя класса, а objectBoxCollider — это его экземпляр..

К тому же Unity3d очень активно использует наследование (хотя бы взять любой скрипт — он наследован от MonoBehavior. Нужно знать как работает наследование и какой базовый функционал (и какие свойства) уже доступны «из коробки» у любого класса, который будет наследован от него.
Всё-таки Unity3D подразумевает, что у разработчика есть базовые знания C#, или JS. Я бы вам порекомендовал вначале почитать статьи с замечательного сайта https://metanit.com/sharp/tutorial/
Лучше чем там я объяснить всё равно не смогу ��

оО, о как, очень рад что сайт живой,ато вновь и вновь прочёсываю инет своими тегами, гляжу — котодомик))
думаю — та-ак, помню что там чтото полезное было пойду ещё загляну) а тут опаньки, живая планета,.
только вот пользователи сетей видать не очень жалуют домен «рф» и встречается он редковато,
буду значит наблюдать за сайтом,по возможности единомышленников подтягивать,
пс
C#

transform.position += new Vector3(1,0,0); // добавляем к X единице (смещаем на единицу)
transform.position += new Vector3(1,0,2)*Time.deltaTime; // двигаем объект в реальном времени с установленными значениями
по осям х и z

int speed = 5;
void Start()
transform.position += new Vector3(speed,0,0)*Time.deltaTime;//движение по оси х с заданием параметра(скорости) через переменную speed
transform.position += new Vector3(1,0,1)*speed*Time.deltaTime;// движение по заданным осям со скоростью установленной переменной speed

вот типа того бы, с пояснениями и дальнейшим развитием их применения
ещё поподробней бы про кватернионы и ейлеры, каким образом кватернион вывести в вектор3
про ригидбоди — нет нигде информации, как ограничивать угол поворота по осям,матф.кламп
как использовать драг по разным осям с разным значением
гравитация и енерция их ограничения и направления,
почему объект в вертикальном положении может подвергаться гравитации а в горизонтальном уже нет..+-

45ˆ
подробного про get set не хватает с примерами, пишут что много чего можно делать, а примеров нет, даже въехать сложно как выжать из него пользу чтобы фантазия стартонула….
учил с++ по Шилдту,3 изд,(в с# (юнити) нету чтоле *и& ?(ссылки, указатели) что то не встречал в скриптах)
так вот чего там нехватает — примеров хотябы с кошками и блошками
тут ещё надо въехать в API, как спаять школьный мелок с мышкой и клавой
а так — ждём продолжения ,всё довольно доходчиво преподносится..

Спасибо за отзыв! Приятно! ��
Стараюсь поддерживать актуальность сайта по мере сил и возможности.

Отдельное спасибо за темы для новых статей.

Спасибо очень сильно помог, ещё раз большое спасибо.

есть vector3 как взять по нему gameObject?

Здравствуйте. К сожалению никак. Vector3 это структура данных, которая содержит информацию о точках X,Y,Z.
Vector3, как и Vector2 стоит рассматривать наравне с int, string, bool, float..

Например. Контейнер gameObject всегда содержит ссылку на компонент (обязательный) transform.
А transform содержит много свойств, отвечающих за позицию и размер объекта на сцене. Одно из свойств, как раз position — является Vector3.

Через любой компонент можно получить ссылку на gameObject, как и через gameObject можно получить ссылку на любой компонент, который данный gameObject содержит внутри себя.
Например: var boxColl >();
Но Vector3 не является компонентом в Unity3D.

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

Спасибо за хорошо изложенную информацию) Сделал по туторам три простеньких игру, просто повторяя все за автором курса. Но во многое не въехал. Тут почитал, многое встало на свои места сразу. У вас талант к ясному изложению. Не бросайте это дело)

Здравствуйте! Большое спасибо за ваш отзыв ��
К сожалению сейчас нет особой возможности вести блог.
Но если у вас есть какие-то конкретные вопросы по Unity3D, то я могу с удовольствием на них ответить.

Разработка вашей первой игры с помощью Unity и C#. Часть 2

Продукты и технологии:

Unity, C#, Microsoft .NET Framework

В статье рассматриваются:

  • работа с двухмерной графикой в Unity;
  • спрайты;
  • распространенная функциональность, в том числе коллайдеры, учет попаданий (очков) и анимация;
  • создание заготовок (prefabs) для повторного использования.

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

2D в Unity

Чтобы получить поддержку 2D в Unity при создании нового проекта, выберите 2D из раскрывающегося списка в диалоге создания нового проекта. После этого все свойства проекта по умолчанию подстраиваются под 2D (можно увидеть в Edit | Project Settings | Editor), и любые изображения, импортируемые в ваш проект, становятся спрайтами, а не просто текстурами. (Об этом я расскажу подробнее в следующем разделе.) Кроме того, представление сцены переключается по умолчанию в режим 2D. На самом деле в этом режиме просто предоставляется вспомогательная кнопка, которая фиксирует две оси при разработке сцены, но никак не влияет на саму игру. Вы можете щелкнуть ее в любой момент, чтобы войти в режим 2D или выйти из него. 2D-игра в Unity реально остается 3D-средой — просто ваша работа ограничивается осями X и Y. На рис. 1 и 2 показаны варианты с выбранным режимом 2D и без него. Я выделил камеру, чтобы вы видели контуры области просмотра камеры, но она смотрит в пространство как фигура прямоугольной формы.

Рис. 1. Режим 2D выбран — камера имеет фокус


Рис. 2. Режим 2D не выбран — камера имеет фокус

2D-игра в Unity реально остается 3D-средой — просто ваша работа ограничивается осями X и Y.

Выделенная камера настроена как прямоугольная (orthographic camera) — это один из двух режимов камеры в Unity. Этот тип камеры, широко применяемый в 2D, не масштабирует объекты, отстоящие дальше от ваших глаз, т. е. нет глубины от позиции камеры. Другой тип камеры — перспектива (perspective), которая показывает объекты так, как их видят ваши глаза, с глубиной. Причин использовать каждый из типов камеры много, но, как правило, следует выбирать перспективу, когда требуется визуальная глубина, если только вы не хотите соответственно масштабировать свои объекты. Вы можете сменить тип камеры, просто выбрав камеру и изменив тип проекции. Советую опробовать это и посмотреть, как изменяется область просмотра вашей камеры, когда вы начинаете смещать объекты дальше от глаз по оси Z. Режим по умолчанию можно сменить в любой момент, что повлияет только на изображения, которые будут потом импортироваться в ваш проект.

Когда по умолчанию выбран режим 3D, изображения распознаются как тип Texture.

Если у вас есть существующий проект в Unity или если вы не уверены, выбран ли режим 2D в диалоге проекта, то можете задать свойствам проекта значения по умолчанию для 2D через Edit | Project Settings | Editor; иначе вам придется вручную задавать тип каждого импортируемого вами 2D-изображения, что несколько утомительно при большом количестве изображений.

Все дело в спрайте

Когда по умолчанию выбран режим 3D, изображения распознаются как тип Texture. Перетащить текстуру в сцену нельзя; текстура должна быть применена к какому-то объекту. Создавать 2D-игры таким путем вовсе не забавно. Я хочу просто перетаскивать изображения, чтобы они появлялись в моей сцене. Однако, если режим по умолчанию — 2D, все становится проще. Теперь, когда я перетаскиваю изображение в Unity, оно распознается как тип Sprite.

Это позволяет перетаскивать в Unity все изображения, образующие графику игры, а затем из Unity в сцену. Если какие-то изображения выглядят мелкими, то вместо их масштабирования везде, где они встречаются, вы можете просто уменьшить значение Pixels To Units. Это очень распространенная операция в Unity как для 2D, так и для 3D и обычно более производительная, чем масштабирование объектов через свойство scale преобразования.

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

  1. Вы задаете свойство Sorting Layer в Sprite Renderer.
  2. Вы задаете свойство Order in layer в Sprite Renderer.
  3. Вы задаете значение позиции по оси Z в Transform.

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

Уровни сортировки рисуются в порядке определения. Когда вы добавляете другие уровни (в Edit | Project Settings | Tags and Layers), Unity сначала рисует любой объект, который обнаруживается в уровне Default (затем учитывается Order in Layer, потом — значение позиции по оси Z в Transform), далее Background, Platforms и т. д. Поэтому вы можете легко поправить перекрытие объектов, присвоив их уровню Platforms, а объекту, который должен быть поверх, указав Order in Layer со значением 1; тогда он будет нарисован после всего, что имеет Order in Layer, равный 0.

Распространенная функциональность

На рис. 3 показан уровень, содержащий некоторые изображения платформ и фона, которые были созданы перетаскиванием и заданием уровней сортировки (sorting layers).

Рис. 3. Игровой уровень

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

Перемещение с помощью клавиатуры, мыши и жестов В Unity клавиатура, мышь, акселерометр и сенсорный ввод считываются через систему ввода. Это легко делается с помощью скрипта наподобие показанного ниже в основном уровне (вскоре я расширю этот скрипт):

Если вы проверите Edit | Project Settings | Input, то увидите варианты ввода по умолчанию (Unity предоставляет целый набор таких вариантов в каждом новом проекте) и сможете задать новые. На рис. 4 показаны умолчания для считывания перемещения по горизонтали. Параметры left и right представляют клавиши-стрелки «влево» и «вправо», но заметьте, что для перемещения по горизонтали используются «a» и «d». Их можно сопоставить со вводом от джойстика. Вы можете добавить новые значения или изменить умолчания. Поле Sensitivity контролирует, насколько быстро Unity будет проходить от 0 до 1 или –1. При нажатии стрелки вправо первый кадр может получить значение .01, а затем возможно довольно быстрое ускорение до 1, хотя скорость можно подстроить так, чтобы игровой персонаж мгновенно получал горизонтальную скорость. Вскоре я покажу код для применения этих значений к вашим игровым объектам. Для чтения этих значений необходимость в компоненте GameObject на самом деле нет; вы просто используете ключевое слово Input в своем коде для доступа к функциональности, обеспечивающей чтение ввода. Как общее правило, ввод следует считывать в функции Update в противоположность FixedUpdate, чтобы избежать потери событий ввода.

Рис. 4. Значения по умолчанию для ввода перемещений по горизонтали

Линейное перемещение Вещи нужно иметь возможность перемещать. Если это игра, где экран прокручивается сверху вниз (top-down game), то гравитация обычно не играет важной роли. Если же это аркада (platformer), гравитация, наоборот, крайне важна. В любом случае обнаружение коллизии объектов весьма критично. Вот базовые правила. Компонент Rigidbody2D или RigidBody (используется для 3D), добавленный к игровому объекту, автоматически придаст ему массу, сделает его поддерживающим гравитацию и способным реагировать на прикладываемые к нему силы. Согласно Википедии: «В физике абсолютно твердое тело (rigid body) является идеализацией твердого тела (solid body), в котором пренебрегается деформацией. Другими словами, расстояние между любыми двумя данными точками абсолютно твердого тела остается постоянным во времени независимо от действующих на него внешних сил». Тот же принцип применяется в играх. Добавление абсолютно твердого тела позволяет вам делает вызовы наподобие показанных на рис. 5.

Рис. 5. Добавление перемещения и скорости

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

Обнаружение коллизий Объект получает массу от своего компонента RigidBody, но, кроме того, вы должны сообщить Unity, как обрабатывать коллизии с этим объектом. Здесь размер и форма ваших изображений или моделей не имеют значения, хотя масштабирование все же влияет на физику самого объекта. Важны размер и форма компонента коллайдера (collider component), который представляет собой просто определенную область вокруг или внутри объекта, для которого нужно, чтобы Unity обнаруживала соприкосновение с другим объектом. Это обеспечивает поддержку таких ситуаций, когда вы входите в область неактивного зомби или когда при приближении к горе на вас скатывается валун.

Коллайдеры бывают самых разнообразных форм. Коллайдер для 2D может быть окружностью, границей (гранью), многоугольником или прямоугольником. Прямоугольные коллайдеры хороши для объектов с формой наподобие квадратов или прямоугольников, или когда вы просто хотите обнаруживать коллизии в квадратной области. Подумайте о платформе, на которой вы стоите, — это хороший пример прямоугольного коллайдера. Простое добавление этого компонента к вашему игровому объекту позволяет задействовать преимущества физических столкновений. На рис. 6 я добавил персонажу коллайдер в виде окружности и абсолютно твердое тело, а к платформе — прямоугольный коллайдер. Когда я запускаю игру в Editor, игрок немедленно падает на платформу и останавливается. Никакого кода не требуется.

Рис. 6. Добавление коллайдеров

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

Объект получает массу от своего компонента RigidBody, но, кроме того, вы должны сообщить Unity, как обрабатывать коллизии с этим объектом.

Если я хочу, чтобы Unity вызывала мой код, когда впервые происходит этот случай коллизии, то просто добавляю следующий код в игровой объект через компонент скрипта (о нем мы говорили в предыдущей статье):

Триггеры Иногда нужно обнаруживать коллизию, но безо всякой физики. Возьмите такую ситуацию, когда вы подбираете в игре какой-то ценный предмет. Вы же не хотите, чтобы монеты разлетелись перед игроком, когда он подойдет к ним; вам нужно, чтобы монеты были собраны и никак не мешали перемещению игрока. В этом случае используется коллайдер, который называется триггером. Это не более чем коллайдер с помеченным флажком IsTrigger в его свойствах. Тем самым физика отключается, и Unity будет лишь вызывать ваш код, когда объект A (содержащий коллайдер) попадет в область объекта B (тоже содержащего коллайдер). В данном случае в коде применяется метод OnTriggerEnter2D вместо OnCollisionEnter2D:

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

Одна вещь, о которую часто спотыкаются разработчики-новички, — поведение абсолютно жестких тел при добавлении к ним коллайдеров. Если в моем объекте есть коллайдер, имеющий форму окружности, и я помещаю этот объект на наклонную плоскость (как указывается формой ее коллайдера), он начинает катиться (рис. 7). Это моделирует то, что вы видите в физическом мире, когда колесо попадает на склон. Я не использую прямоугольный коллайдер для своего персонажа из-за того, что у этого коллайдера есть границы, которые могут задевать границы других коллайдеров, что будет приводить к перемещению с рывками. Коллайдер с формой окружности обеспечивает более плавное перемещение. Однако, когда плавное вращение неприемлемо, вы можете использовать параметр Fixed Angle в компоненте Rigidbody.

Рис. 7. Применение коллайдера с формой окружности для плавного перемещения

Звук Чтобы слышать звук, нужен компонент Audio Listener, который по умолчанию существует в любой камере. Для проигрывания звука просто добавьте компонент Audio Source к игровому объекту и укажите аудиоклип. Unity поддерживает большинство основных форматов звука и будет кодировать более длинные клипы в MP3. Если у вас множество источников звука с клипами, назначенными в Unity Editor, учитывайте, что все они будут загружены в период выполнения. Вместо этого вы можете загружать звук через код, размещенный в специальной папке ресурсов и уничтожать его, когда он больше не нужен.

Импортировав звук в свой проект, я сохранил его как WAV-файл, который представляет собой несжатое аудио. Unity перекодирует более длинный звук для оптимизации, поэтому всегда используйте звук максимального качества, которым вы располагаете. Это особенно верно для коротких файлов вроде звуковых эффектов, которые Unity не станет кодировать. Я также добавил компонент Audio Source к своей главной камере, хотя мог бы добавить его к любому игровому объекту. Затем я назначил аудиоклип Adventure этому компоненту Audio Source и сбросил флажок Loop, поэтому он постоянно проигрывается как петля. Три простых шага, и теперь в игре есть фоновая музыка.

GUI/элементы HUD (Heads-Up Display) Система GUI может охватывать многие вещи в игре. Она может включать систему меню, индикатор здоровья, текущий счет, арсенал оружия и др. Как правило, систему GUI вы постоянно видите на экране независимо от того, куда смотрит камера (хотя это не обязательно). GUI-функционал в Unity в настоящее время полностью перерабатывается, и в Unity 4.6 появится новая система uGUI. Поскольку эта версия еще не вышла, мы рассмотрим здесь лишь некоторую базовую функциональность, но, если вас интересуют подробности о новой системе GUI, загляните в мой блог на channel9 по ссылке channel9.msdn.com/Blogs/AdamTuliper.

Чтобы вывести на экран простой текстовый дисплей (например, score: 0), я открыл Game Object | Create Other | GUI Text. Этой команды в Unity 4.6 больше нет, поэтому советую посмотреть видеоролик по uGUI, о котором я упоминал. В версии 4.6 по-прежнему можно добавить компонент GUI Text к игровому объекту, щелкнув кнопку Add Component; он просто убран из меню Editor. В существующей (устаревшей) системе GUI в Unity вы не можете увидеть свои GUI-объекты в представлении сцены — только в представлении Game, что превращает создание разметки в несколько странное занятие. Если хотите, используйте чисто программный подход к настройке своего GUI, и для этого есть класс GUILayout, позволяющий автоматически отслеживать виджеты. Но я предпочитаю систему GUI, где можно легко работать, используя мышь; вот почему я нахожу гораздо совершеннее систему uGUI. (До uGUI лидером в этой области был довольно основательный сторонний продукт — NGUI, который и задействовали как исходную кодовую базу для uGUI.)

Самый простой способ обновлять текстовый дисплей — найти и назначить в Editor ссылку на игровой объект с этим GUIText и обрабатывать его подобно метке в .NET, обновляя его свойство text:

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

Отслеживание счета Это несложная задача. У вас просто есть класс, предоставляющий открытый метод или свойство, с помощью которого задается счет. В играх обычно есть объект Game Controller, действующий как организатор игры. Game Controller может отвечать за инициацию сохранений игры, загрузку, учет текущего счета и др. В этом примере у меня есть класс, предоставляющий переменную score, как показано на рис. 8. Я назначаю этот компонент пустому игровому объекту, чтобы он был доступен при загрузке сцены. Когда счет обновляется, происходит обновление и GUI. Переменная _scoreText назначена в Unity Editor. Просто перетащите любой игровой объект с GUIText на это поле или используйте виджет поиска, где данный компонент скриптов предоставляет переменную Score Text в редакторе.

Рис. 8. Создание переменной _scoreText

После этого я могу просто обновить (в данном примере) код триггера гриба для увеличения счета при каждом подборе ценного предмета:


Анимации Как и в XAML, анимации создаются выполнением различных действий в ключевых кадрах. Я мог бы легко посвятить целую статью одним только анимациям в Unity, но буду краток из-за нехватки места. В Unity есть две системы анимации: устаревшая и более новая — Mecanim. В устаревшей системе используются файлы анимации (.ani), а в Mecanim — состояния, управляющие тем, какой файл анимации воспроизводится.

В двухмерной графике по умолчанию применяется Mecanim. Самый простой способ создать анимацию — перетащить изображения в сцену и разрешить Unity создать анимацию за вас. Для начала я перетащил некоторые отдельные спрайты в Unity, а та в свою очередь создала за меня несколько вещей. Прежде всего она создала игровой объект с компонентом рендера спрайтов (sprite renderer component) для рисования спрайтов. Затем — файл анимации. Вы можете увидеть это, перейдя в Window | Animator и выделив свой игровой объект. Аниматор показывает назначенный файл анимации, который в моем случае содержит шесть ключевых кадров, поскольку я перетащил в сцену шесть изображений. Каждый ключевой кадр контролирует один или более параметров в каком-либо компоненте; здесь изменяется свойство Sprite компонента Sprite Renderer. Анимации — это не более чем отдельные изображения, показываемые с некоей частотой, воспринимаемой глазом как движущиеся картинки.

Далее Unity создала компонент Animator в игровом объекте, как показано на рис. 9.

Рис. 9. Компонент Animator, указывающий на контроллер

Этот компонент указывает на простой конечный автомат, называемый контроллером анимации. Это файл, создаваемый Unity, который просто показывает состояние по умолчанию; иначе говоря, он всегда находится в состоянии «idle» («простаивает»), так как это единственное доступное состояние. Это состояние простоя ничего не делает, а просто указывает на мой файл анимации. На рис. 10 представлены реальные данные ключевых кадров на временном графике.

Рис. 10. Анимационные данные в простое

Может показаться, что для подготовки анимации требуется много усилий. Однако мощь конечных автоматов в том, что вы можете управлять ими, задавая простые переменные. Вспомните: состояние не делает ничего — только указывает на файл анимации (хотя в 3D можно изощряться и делать такие вещи, как смешивание анимаций).

Затем я взял больше изображений, что создать анимацию run (run animation) и перетащил их на свой игровой объект Yeti. Так как у меня уже есть компонент аниматора в этом объекте, Unity просто создает новый файл анимации и добавляет новое состояние «run» («выполняется»). Я могу просто щелкнуть правой кнопкой мыши состояние idle и создать переход к run. При этом появляется стрелка между состояниями idle и run. Далее можно добавить новую переменную Running, использовать которую очень легко: вы просто щелкаете стрелку между состояниями и изменяете условие использования этой переменной, как показано на рис. 11.

Рис. 11. Смена состояний из idle в run

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

Рис. 12. Смена состояния программным способом

В моем примере я использовал отдельные спрайты для создания анимации. Однако довольно часто используют ленту спрайтов (sprite sheet) — один файл более чем с одним изображением в нем. Unity поддерживает ленты спрайтов, так что достаточно сообщить Unity, как разделить на части ваш спрайт, а затем включить эти части в вашу сцену. В этом случае от вас потребуется выполнить ряд операций: сменить в свойствах спрайта Sprite Mode с Single на Multiple и открыть Sprite Editor, который потом сможет автоматически поделить спрайт и применить изменения, как показано на рис. 13. Наконец, вы раскрываете спрайт (в режиме просмотра проекта на значке спрайта есть небольшая стрелка), выделяете полученные спрайты и перетаскиваете их в свою сцену, как обычно.

Рис. 13. Создание ленты спрайтов

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

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

Игровой объект и его соответствующие свойства показаны на рис. 14. Заметьте, что высота коллайдера достаточно велика, чтобы игрок не мог перепрыгнуть через него, и, кроме того, этот коллайдер настроен как триггер.

Рис. 14. Игровой объект и его свойства

Ход игры (game play) В просто 2D-игре вроде этой поток управления довольно прямолинеен. Игрок начинает игру. Гравитация абсолютно твердого тела заставляет персонаж в игре упасть. У персонажа и платформы есть по коллайдеру, поэтому персонаж останавливается. Считывается сенсорный ввод, от клавиатуры и мыши, что приводит к перемещению игрового персонажа. Игрок перепрыгивает между платформами с помощью rigidbody.AddForce, который заставляет персонаж прыгнуть, и перемещается влево и вправо за счет считывания Input.GetAxis(«Horizontal») и его применения к rigidbody.velocity. Игрок собирает грибы, которые являются коллайдерами, настроенными как триггеры. Когда игрок касается их, они увеличивают счет и разрушаются. Как только игрок доходит до финала уровня, срабатывает триггер, перезагружающий текущий уровень. Здесь следовало бы добавить большой коллайдер под землей, чтобы обнаруживать, когда игрок сваливается с платформы, и просто перезагружать уровень.

Заготовки (prefabs) Повторное использование важно как в кодировании, так и в дизайне. Назначив своим игровым объектам несколько компонентов и настроив их, вы будете часто использовать их снова и снова в рамках одной сцены или даже нескольких сцен либо игр. Вы можете создать другой экземпляр игрового объекта в сцене, но также можете создать экземпляр заготовки, которой пока нет в вашей сцене. Возьмем, к примеру, платформы и их коллайдеры. Если вы хотите повторно использовать их в других сценах, то, увы, на данный момент это невозможно. Но, создав заготовки, вы получаете нужную возможность. Просто перетащите любой игровой объект из иерархии обратно в папку проекта, и будет создан новый файл с расширением .prefab, содержащий любые дочерние иерархии. Теперь вы можете перетаскивать этот файл в другие сцены и повторно использовать его. Исходный игровой объект теперь оказывается соединенным с заготовкой. Обновление файла .prefab обновляет все экземпляры в ваших сценах; кроме того, вы можете оправлять изменения из модифицированной заготовки сцены обратно в файл .prefab.

Щелкнув заготовку, вы увидите содержащиеся в нем игровые объекты, как показано на рис. 15. Если вы внесете здесь изменения, все экземпляры в вашей сцене будут обновлены.

Рис. 15. Просмотр содержимого заготовки

Заключение

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

Дополнительные материалы для изучения

  • Данный проект в скомпилированном виде channel9.msdn.com/Events/Build/2014/2-503.
  • Microsoft Virtual Academy. «Developing 2D & 3D Games with Unity for Windows» aka.ms/UnityMVA.
  • Блог Adam’s Channel 9 aka.ms/AdamChannel9.
  • Ресурсы Unity unity3d.com/learn.

Адам Тьюлипер (Adam Tuliper)старший идеолог по технологиям в Microsoft; живет в солнечной Южной Калифорнии. Разработчик инди-игр, один из администраторов Orange County Unity Meetup и автор на pluralsight.com. Скоро в его семье появится третий ребенок, так что связывайтесь с ним, пока у него еще есть свободные минуты, по адресу adamt@microsoft.com или через twitter.com/AdamTuliper.

Выражаю благодарность за рецензирование статьи экспертам Мэтту Ньюмену (Matt Newman) из Subscience Studios и Тоутвидасу Цилису (Tautvydas Žilys) из Unity.

Использование struct (Структуры) в Unity (C#)

Пост предназначен для новичков в программировании.

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

Структуры могут быть полезны в ряде моментов в программировании логики игры, например в играх как 4 фотографии 1 слово, системы инвентарей и.т.д.

Начнем с объявления структур.

Структуры определяются ключевым словом struct. Тело структуры открывается и закрывается фигурными скобками. В целом, структура во многом похоже на класс, но не поддерживает полиморфизм и наследование.

Например, возьмем в качестве примера структуру Cost

P.S. [System.Serializable] используется для сериализации структуры в инспекторе.

Как можно увидеть, структура хранит в себе целочисленные типы данных (int), такие как НормальнаяЦена, МинимальнаяЦена и МаксимальнаяЦена. Эту структуру можно использовать для рандомизации цены объекта, например как в моем текущем проекте «Симулятор перепродажи».

Так же, структура может иметь в себе конструктор :


Конструктор используется для быстрого заполнения данных (переменных) в структуре.

Данную структуру можно заполнить 3 способами :

1. Ручным методом заполнить все 3 переменные.

2. Использовать конструктор и ключевое слово new

3. Использовать инспектор Unity

Первый и второй способ может быть полезен например при генерации мира.

1. Структура Блок, хранящий в себе ИД блока и позицию

2. Способ заполнения конструктором

Заметьте, что [System.Serializable] тут не используется, так как нам не нужно вручную заполнять структуру в инспекторе. Но, для дебага (отладки) оно может быть необходимо.

Вернемся к теме структуры Cost. Для использования данной структуры в полной мере была создана еще одна структура под названием Item (вещь).

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

Для отображения в инспекторе был поставлен параметр [System.Serializable].

Эта структура хранит в себе название, описание вещи, его спрайт, онлайн-картинка и шанс выпадения (в комментариях — от 0 до 100%) и цену. Для его инициализации в классе наследуемом MonoBehaviour была написана данная строчка :

Имеется массив с используемыми в игре объектами. Для его заполнения я буду использовать инспектор, так что от конструктора отказался. В инспекторе это дело выглядит так :

Как видим, мы заполнили 1 структуру Item информацией о Xbox One (цены брал на рандоме). Для использования переменных, например, чтобы показать этот объект на сайте, пишем название_массива[i].название_переменной, где i — номер объекта (в данном случае 0).

Теперь, давайте же заполним UI Image и UI Text-ы нашими данными. Для этого я быстро создал простенький UI

Затем, немного доработал скрипт, добавил переменные с текстами и картинками и метод Старт.

P.S. Цена выбирается рандомно между минимальной и максимальной ценой.

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

Если слишком шакалисто — Xbox One; Cool new Xbox One; 353$ и буква X :)

Ну, на этом то и все, спасибо что прочитали мой пост :)

Баянометр показывает сходство с постом про Ведьмака.

Найдены возможные дубликаты

[System.Serializable] используется для сериализации структуры в инспекторе.

Вроде хорошо начал, но как-то быстро закончил теорию и перешел к примеру. А пример оказался не показателен, с классами было бы тоже самое. Структуры интересны в контексте их отличия от классов, на этом и надо было заострить внимание, но это так на будущее))

думаю, поскриптум лучше перенести в начало статьи)

Хорошо, перенесу) Спасибо за замечание :)

Спасибо что ты есть, чел! Накоц-то разобрался, как сделать себе магазин со шмотками

Дети совсем обленились. Читать книги, документацию — неее. Посты на пикабу.

Если судить по твоим постам, то тебе еще нет 18 лет. А значит ты еще дитё, которое обленилось и зашло на пикабу прочитать про c#, а читать книги, документацию — неее. :|

Лул. Что и требовалось доказать..дитё.

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

Твое развитие на уровне 15 лет. Ок?

О сообществе

Разработка видеоигр и всё, что с этим связано. Концепции, иллюстрации, 3D-моделирование, программирование и многое другое геймдев-направленности.

-Уважайте чужой труд и используйте конструктивную критику

-Не употребляйте мат без необходимости

-Посты определённой тематики стоит помечать соответствующими тегами (см. последний пункт).

-Пост о Вашей игре, желательно — с историей разработки и описанием полученного опыта

-Обучающие посты, туториалы

-Интервью с именитыми разработчиками

-Анонсы бесплатных мероприятий для разработчиков и истории их посещения;
-Ваши работы, если Вы художник/композитор и хотите поделиться ими на безвозмездной основе


НЕ НУЖНО ПУБЛИКОВАТЬ:

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

-Посты, единственная цель которых — набор команды для разработки игры по вашей гениальной идее

-Посты, не относящиеся к тематике сообщества

Подобные посты по решению администрации могут быть перемещены из сообщества в общую ленту.

-Публиковать бессодержательный пост с рекламой Вашего проекта (см. следующий пункт), а также все прочие посты, содержащие рекламу/рекламные интеграции

-Выдавать чужой труд за свой

Подобные посты будут удалены, а авторы таких постов будут внесены в игнор-лист сообщества.

Ссылка на сторонний ресурс, связанный с игрой, допускается только при следующих условиях:

-Пост должен быть содержательным и интересным для пользователей

-Ссылка должна размещаться непосредственно в начале или конце поста и только один раз.

-Cсылка размещается в формате: «Страница игры в Steam: URL»

СПЕЦИАЛЬНЫЕ ТЕГИ СООБЩЕСТВА:

Не всем интересны посты на определённую тематику. В тоже время, некоторым особо интересна конкретная тема. Пожалуйста, помечайте посты указанными тегами, если они соответствуют приведённым темам:

«Gamedev-Interview» — интервью с известными разработчиками

«Gamedev-Event» — объявления о мероприятиях для разработчиков

«Gamedev-Assets» — посты с вашими бесплатными ассетами

Использование компонентов.

Использование компонентов. Править

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

Объект игры — контейнер для различных компонентов. По умолчанию все объекты автоматически получают компонент Transform. Это потому, что Трансформ определяет где расположен Объект, как он повернут и масштабирован. Без этого компонента не имеет местоположения в мире. Попробуйте теперь для примера создать пустой Объект. Щелкните в меню GameObject->Create Empty (Объект->создать пустой). Выберите новый объект и посмотрите в Инспектор.

Каждый пустой объект имеет компонент Transform

Помните, что Вы всегда в Инспекторе можете увидеть какие компоненты прикреплены к выбранному Объекту. Когда компонент добавляется или удаляется Инспектор всегда показывает Вам изменения. В Инспекторе Вы всегда можете изменить свойства компонента (включая скрипты).

Добавление компонентов Править

Вы можете добавить Компоненты к выбранному Объекту игры через меню компонентов. Мы попробуем сделать это сейчас добавив Ригидбоди к только что созданному Объекту. Выберите объект и перейдите в меню Component->Physics->Rigidbody. После этого Вы увидите свойства компонента Ригидбоди в Инспекторе. Если Вы нажмете Play Вы можете удивиться. Попробуйте и увидите как Ригидбоди изменило поведение объекта, добавив к нему новую функциональность (смотрите на y-компоненту позиции объекта — она уменьшается. Это потому что физический движок теперь заставляет объект падать под действием гравитации).

Пустой объект с прикрепленным компонентом Rigidbody

Другая возможность добавить компонент — активировать Браузер компонентов, который открывается кнопкой Добавить компонент (Add Component) в Инспекторе.

Вы можете прикрепить любое число или комбинацию компонентов к одному Объекту игры. Некоторые компоненты работают в комбинации с другими. Например Ригидбоди работает с Коллайдером. Ригидбоди управляет трансформациями через физический движок NVIDIA PhysX, а коллайдер позволяет Ригидбоди взаимодействовать с другими коллайдерами.

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

Редактирование компонентов Править

Один из самых крутых плюсов применения компонентов — гибкость. Когда Вы прикрепляете компонент к Объекту, появляется возможность настройки различных свойств компонента в редакторе перед сборкой игры, или из скрипта во время запуска игры. Есть два главных типа свойств — Значения и Ссылки.

Посмотрите на рисунок ниже. Это пустой Объект с компонентом Источник Аудио (Audio Source). Все значения компонента в Инспекторе установлены по умолчанию.

Изменение свойств объекта в коде

Как изменить свойства объекта? В частности меня интересуют физические свойства (масса и т.д.), которые можно изменить в визуальном редакторе изначально. Гуглил, смотрел темы, но всё не то. Заранее благодарю.

Странно, я в свое время с гуглом справился.

Сабж:
GameObject.ИщемОбъект.ПолучаемЕгоКомпонент().Обращаемся-к-свойству-компонента = устанавливаем значение

Псевдокод для той самой массы:
GameObject.FindGameObjectWithTag(«НЕЧТО»).GetComponent ().mass = 1.0f;

Если скрипт уже висит на объекте, искать его беспонту:

Как прикрепить свойство TextMesh к клонированному объекту в Unity 3D

Я генерирую динамические экземпляры объекта класса в Unity 3D и работаю хорошо, но, когда я пытаюсь добавить дополнительный компонент TextMesh , я не могу получить к ним доступ для назначения текста. Коды:

Bubble.cs

Но, когда я пытаюсь получить доступ к свойству nText всегда имеет значение null . Кроме того, я не могу связать этот TextMesh с компонентом, определенным в сцене, потому что все пузырьки должны иметь разные значения.


Как, я могу это исправить?

Ошибка: UnassignedReferenceException: The variable nText of Bubble has not been assigned. You probably need to assign the nText variable of the Bubble script in the inspector. UnassignedReferenceException: The variable nText of Bubble has not been assigned. You probably need to assign the nText variable of the Bubble script in the inspector.

Рецепт: Создание новых объектов во время выполнения (Unity C#)

Игры включают в себя не только управление одним персонажем, но и динамическое создание новых игровых объектов. Для создания объектов и существуют префабы (prefabs). В таком случае, что же такое префаб? Вы можете найти множество определений но я постараюсь объяснить как можно проще.

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

Давайте начнём, создайте куб на сцене и отредактируйте его так как хотите. Затем создайте папку Prefabs и перетащите туда куб. Это всё! Вы создали префаб, теперь вы можете удалить куб со сцены. У нас есть точная копия этого куба и мы будем её использовать во время выполнения.

Доступ к свойствам в Unity3D

Я хочу спросить, зачем использовать ‘сферу’ для доступа к transform.position, который является sphere.transform.position в script1. Но в скрипте2 мы можем напрямую оценить transform.Rotate без каких-либо объектов до него, почему бы не написать: sphere.transform.Rotate?

script1

Скрипт2

Создан 13 июл. 17 2020-07-13 10:45:12 gakutano

** Script2 ** изменяет преобразование вращения текущего родительского объекта. ** Script1 ** изменит преобразование вращения объекта, не связанного с этим конкретным скриптом. Это не вопрос, связанный с Единством, а вопрос об основах ООП. – m.rogalski 13 июл. 17 2020-07-13 10:52:24

1 ответ

Как вы можете видеть here, .transform позволяет получить доступ к Transform компонент из игрового объекта. Если вы просто используете transform , то он будет таким же, как если бы вы использовали this.transform , он вернет компонент Transform, прикрепленный к тому же игровому объекту, к которому привязан сценарий вызывающего абонента.

Таким образом, в вашем примере, в srcipt1 вы вызываете Transform компонент из разных игровых объектов, но в Скрипт2 вы вызываете компонент одного и того же игрового объекта.

Создан 13 июл. 17 2020-07-13 10:54:17 Dávid Florek

Введение в программирование C# на Unity

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

Unity поддерживает следующие языки программирования: C# и Javascript. Языки C# и Javascript считаются одними из самых популярных среди программистов. На C# пишутся программы для компьютера, веб приложения, а Javascript активно используется для создания интернет-страниц. В нашем случае:

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

Чтобы писать скрипты, необходим редактор кода. В комплекте с Unity идет MonoDevelop, так что его не требуется устанавливать отдельно. Другой вариант — использовать Visual Studio — мы рекомендуем ее. Сменить среду разработки можно в настройках: Edit → Preferences, а затем выбери панель External Tools.

Вывод сообщения в консоль Unity

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

Консоль (англ. — Console) – это панель в Unity, которая отображает ошибки в коде (отображаются красным значком), предупреждения (отображается желтым значком) и позволяет выводить справочную информацию (белый значок). По умолчанию эта панель отображается в нижней части программы в закладке Console. Если эта панель не отображается на экране, то в главном меню выбери Window → Console.

Чтобы создать скрипт выбери Assets → Create → C# Script. Имя скрипта должно быть обязательно на английском и начинаться с большой буквы. Открой созданный скрипт и напиши:

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

Код, который должен вызываться один раз при старте программы, ты можешь написать внутри функции Start(), как в примере выше.

Код, который должен вызываться каждый кадр, ты можешь написать внутри функции Update().

Переменные

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

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

  1. Целочисленные: int (от –2 147 483 648 до 2 147 483 647), long (от –9 223 372 036 854 775 808 до 9 223 372 036 854 775 807).
  2. Символы и строки: char (элемент в кодировке UTF-16), string (последовательность элементов в кодировке UTF-16).
  3. С плавающей запятой (дробные): float (от 1,5 × 10–45 до 3,4 × 1038, с точностью до 7 цифр), double (от 5,0 × 10–324 до 1,7 × 10308, с точностью до 15 цифр).
  4. Логические: bool (значение true или false).

Инициализация переменной

Все переменные в C# должны быть объявлены (инициализированы) до их применения. Например:

Задать значение переменной можно, в частности, с помощью оператора присваивания — знак «=». Кроме того, при объявлении переменной можно сразу задать ее значение. Например:

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

+ — операция сложения;

— операция вычитания;

* — операция умножения;

/ — операция деления.

А вот так сумму чисел можно вывести в консоль:

Счетчик времени с помощью Time.deltaTime

Практически во всех играх требуется знать сколько времени прошло с момента запуска игры (пример: игры на время). Но в Unity мы можем узнать только сколько прошло времени между кадрами (напоминаю, что игра – это набор кадров, которые быстро меняются. В одну секунду количество таких кадров может достигать 60 и больше).

Чтобы узнать сколько времени прошло между кадрами — используется Time.deltaTime.

Чтобы сделать дробное число целым, ставим перед ним (int).

Позиция объекта

Координаты объекта хранятся в компоненте Transform, свойство — position. Каждая координата имеет тип float. Вот так можно выводить координаты объекта в консоль:

Цукерберг рекомендует:  Bigdata - Программирование на R. Кто в теме
Понравилась статья? Поделиться с друзьями:
Все языки программирования для начинающих