Туториал 0: Юнити и C# скрипт - основы
Вступление:
Скажу честно, я не программист, так что вполне возможно будут какие-то неточности. Это не игровой туториал. Я постараюсь рассказать, как работают скрипты в Юнити 3Д.С# относительно не сложный язык. Точнее сама основа языка простая, сложности начинаются, когда уже совсем далеко углубляешься в него. Но на самом деле с помощью Юнити3Д можно делать простенькие игрушки только используя основы С#. C# объектно ориентированный язык програмирования. Это пишут все, но как я понял большинство не особо понимает смысл этого, как и я. Но учитывая, что придется работать со скриптами, это не так и важно для начала. Не стоит пытаться создать один огромный трудно понимаемый скрипт для всей игры. Пробуйте разделить игру на части. В свою очередь эти части могут взамодействовать друг с другом. Используйте эти части как кирпичи для создания итоговой игры. В C# используется class, который исполняет роль кирпичика. В Юнити довольно просто создать такой class. Создаете новый C# скрипт и называете его по желанию. И, грубо говоря, созданный скрипт и выполняет роль class в Юнити3Д. Далее можно использовать скрипт как компонет для игрового объекта.
Небольшой пример:
Как пример, решили сделать простенькую космическую стрелялку. Что-то похожее на этот шедевр:В Юнити3Д это будет сцена с множеством игровых объектов: фон, звезды, камера, враг, астероид, игрок... Каждый объект в игре это GameObject. И все GameObjects состоят из Components. Некотрые компоненты заранее заготовленны в Юнити3Д. Как пример: Transform (определяет позицию объекта в пространстве), Sprite Renderer (рисует заданный объект в мире), UI Text (показывает текст в интерфейсе) и много других компонентов. И ваши C# скрипты тоже будут компонентами, которые будут присоединяться к объектам. У C# скриптов есть доступ к другим компонетами. По сути, вся работа со скриптами это просто работа с переменными.
Как использовать C# скрипты ?
Создадим empty GameObject(пустышку) в сцене. У этого объекта уже будет Transform компонент (у каждого объекта в Юнити3Д есть Transform компонент). У созданного объекта пока нет компонента отвечающего за отрисовку, поэтому мы не увидим его игре. Поэтому добавим ешё один компонент Sprite Renderer. И укажем какую картинку должен рисовать этот компонент, например астероид. Тогда мы сможем увидеть астероид в игре.Просто смотреть на астероид скучно, поэтому можно сделать скрипт для его управления.
Не забываем, это не игровой туториал, только вкратце о принципе работы с Юнити3Д.
Создаём новый С# скрипт и называем его(например Moving, так как этот скрипт будет перемещать астероид). Если мы откроем скрипт, то увидим следующую заготовку:
using UnityEngine;
using System.Collections;
public class Moving : MonoBehaviour {
// Use this for initialisation
void Start () {
}
//Update is called once per frame
void Update () {
}
}
Небольшое объяснение строчек: 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 компоненту:
Для удобства есть простой путь доступа на свой Transform компонент, если компонент и скрипт находятся на одном объекте. Просто используете transform. Для доступа на другие компоненты используйте GetComponent (в старых версиях Юнити таких быстрых доступов было больше, не забываем об этом при работе с неактульными туториалами)transform.position = new Vector3 (0, 0, 0);
Если мы хотим сделать это перемещение один раз в начале игры, то нам надо поместить эту строчку в функцию void Start () {}. И наш скрипт будет:
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 () {
}
}
Если мы запустим нашу игру, то астероид будет перемещён в центр игрового мира. 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 () {
}
}
Не забываем, при наборе кода ваш IDE будет пытаться показывать возможные варианты. 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 () {
}
}
Похожим образом мы можем получить и доступ к компонентам на других игровых объектах.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 () {
}
}
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 () {
}
}
Не забываем: используйте GetComponent <ComponentName>();, если хотите получить доступ на отличный от Transform компонент (transform. это просто укороченный вариант для этого компонента). Например если хотите зеркально повернуть корабль по X-оси из скрипта на астероиде, то комманда в C# будет: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 () {
}
}
playerShip.GetComponent < SpriteRenderer > ().flipX = true;
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 переменной). 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 () {
}
}
Наверняка уже заметили, что создание игры в Юнити - это просто работа с переменными в компонентах игровых объектов (я сейчас не говорю о создании музыки, моделей, текстов ... Это уже совсем другая история). Теперь посмотрим на основы С# скриптов. Описание будет довольно коротким и затронет только базовые части. Так что для подробностей придется немножко погуглить или побродить по форумам.