Где скачать скрипты для юнити
Перейти к содержимому

Где скачать скрипты для юнити

  • автор:

Скрипты для редактора в Unity3D

Сегодня поговорим о том, как писать скрипты для Unity Editor. Статья рассчитана на тех, кто уже знаком с Unity3D, что-то успел сделать, но еще не решился попробовать писать скрипты для эдитора.

Если коротко — то в режиме эдитора скриптами можно сделать абсолютно всё тоже самое, что и в режиме игры.

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

public class CreateCubes : MonoBehaviour < // Use this for initialization void Start () < Create10Cubes(); >private void Create10Cubes() < Vector3 position = new Vector3(0, 0, 0); for (int i = 0; i < 10; i++) < GameObject cube = GameObject.CreatePrimitive(PrimitiveType.Cube); cube.transform.position = position; position += new Vector3(5, 0, 0); >> > 

Теперь попробуем выполнить этот код в режиме эдитора, для этого нужно к коду добавить всего лишь один волшебный атрибут [ContextMenu()] к функции Create10Cubes():

так чтобы код выглядел вот так:

[ContextMenu("CreateCubes")] private void Create10Cubes() < Vector3 position = new Vector3(0, 0, 0); for (int i = 0; i < 10; i++) < GameObject cube = GameObject.CreatePrimitive(PrimitiveType.Cube); cube.transform.position = position; position += new Vector3(5, 0, 0); >> 

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

Важное замечание: функция, помеченная атрибутом ContextMenu, не должна иметь параметров, вернее, если у нее будут параметры, вы не сможете вызвать таким способом.

Лично я применяю такой способ, когда нужно что-то сделать с группой объектов, например, выключить отбрасывание теней у всех детей объекта, у которых в названии встречается «withoutshadow»:

[ContextMenu("DisableCastShadows")] private void DisabeCastShadows() < Renderer[] renderers = GetComponentsInChildren() .Where(x => x.name.Contains("withoutshadow")) .ToArray(); foreach (var r in renderers) < r.castShadows = false; >> 

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

Теперь давайте решим следующую задачу: мы хотим запечь occlusion culling. Для этого нам необходимо пометить галочкой Occluder Static все объекты, которые бубдут загораживать другие объекты, и галочкой Occludee Static все, которые будут скрываться за Occluder`ами. То есть нам нужно вычленить все статичные объекты, непрозрачным объкетам поставить обе галки (на самом деле все), прозрачным — только Occludee, а Occluder выключить.

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

Для начала напишем полезный код, который выполняет нашу работу, а далее оформим это в отдельный виззард:

Задачи здесь две:

1) Найти интересующие нас объекты в сцене;
2) Расставить нужные галочки.

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

using UnityEngine; using UnityEditor; using System.Linq; public class SetStaticOclluderFlagsCmd < private const int TransparentQueue = 3000; const int OverlayQueue = 4000; public void Execute() < var scene =Object.FindObjectsOfType(typeof(GameObject)); var transparents = scene.Where(o =>IsStatic(o) && IsTransparent(o)).ToArray(); var occluders = scene.Where(o => IsStatic(o) && !IsTransparent(o)).ToArray(); SceneModeUtility.SetStaticFlags(transparents, (int)StaticEditorFlags.OccluderStatic, false); SceneModeUtility.SetStaticFlags(transparents, (int)StaticEditorFlags.OccludeeStatic, true); SceneModeUtility.SetStaticFlags(occluders, (int)StaticEditorFlags.OccluderStatic, true); SceneModeUtility.SetStaticFlags(occluders, (int)StaticEditorFlags.OccludeeStatic, true); Debug.Log("SetStaticOclluderFlagsCmd done"); > private bool IsStatic(Object obj) < GameObject gameObject = obj as GameObject; if (gameObject == null) return false; return GameObjectUtility.AreStaticEditorFlagsSet(gameObject, StaticEditorFlags.BatchingStatic); >private bool IsTransparent(Object obj) < GameObject gameObject = obj as GameObject; if (gameObject == null ||gameObject.renderer == null) return false; return obj.renderer.sharedMaterials.Any(x =>x.renderQueue >= TransparentQueue && x.renderQueue < OverlayQueue);; >> 

Здесь мы предполагаем, что статичные объекты уже до этого каким то образом нашли (скорее всего ручками) и отметили их галочкой Static, а значит, в том числе и BatchingStatic.

По поводу реализации метода IsTransparent().

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

Теперь давайте оформим отдельный виззард, чтобы можно было удобно вызывать эту команду:

Тут нам пригодится класс EditorWindow.

using UnityEngine; using UnityEditor; public class OcclusionCullingUtilites : EditorWindow < [MenuItem("Window/OcclusionCullingUtilites")] static void Init() < GetWindow(); > void OnGUI() < if(GUILayout.Button("SetStaticFlags")) < SetStaticOclluderFlagsCmd cmd = new SetStaticOclluderFlagsCmd(); cmd.Execute(); >> > 

На этом пока закончим наш обзор, он получился далеко не полным.

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

  • Программирование
  • Разработка игр
  • Unity

Туториал 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 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 компоненту:

Для удобства есть простой путь доступа на свой Transform компонент, если компонент и скрипт находятся на одном объекте. Просто используете transform. Для доступа на другие компоненты используйте GetComponent (в старых версиях Юнити таких быстрых доступов было больше, не забываем об этом при работе с неактульными туториалами)

Позиция в игровом мире это вектор (x,y,z). Если мы хотим поместить астероид в центр, то нам надо изменить координаты вектора на (0,0,0). C# строчка будет:
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 () >
>

Если мы запустим нашу игру, то астероид будет перемещён в центр игрового мира.
Теперь посмотрим на 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 () >
>

Не забываем, при наборе кода ваш IDE будет пытаться показывать возможные варианты.

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

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 () >
>

Не забываем: используйте GetComponent ();, если хотите получить доступ на отличный от Transform компонент (transform. это просто укороченный вариант для этого компонента). Например если хотите зеркально повернуть корабль по X-оси из скрипта на астероиде, то комманда в C# будет:
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 переменной).

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

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

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

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

Spoiler int:
Этот тип переменных может принимать значение целого (не дробного) числа. Переменная лежит в диапазоне от -2 147 483 648 до 2 147 483 647. Обычно используется для подсчета количества объектов или индексации массивов/циклов (о них чуть позже). int score;
int healthPoint = 5 ;
float:
Этот тип для чисел с плавающей запятой (дробные числа). Переменная лежит в диапазоне от -3.4 × 10^38 до +3.4 × 10^38. Обычно используется там, где важна дробная часть (как пример — расстояние до цели). Используйте точку для разделения знаков. float speed;
float distanceToShoot = 10.5 ;
bool:
Это тип переменных имеющих всего два значения true/false (истинно/ложно). Используется в проверке условий (условные операторы). bool isDead;
bool canMove = false;
char:
Тип переменных для символов Юникода. Например отдельные буквы. Используйте одинарные кавычки при инициализации. char litera;
char firstLitera = ‘A’ ;
string:
Тип переменных для символьной последовательности/текст (на самом деле это ссылочная переменная, то есть в ней хранится ссылка на область памяти, где находится эта символьная последовательность. Но её принцип работы похож на обычные переменные). В классе string содержится несколько функций. Одна из них string.Length, позволяющая узнать количество символов в строке. Для инициализации используйте кавычки. string newText;
string enemyText = «Stop! Don’t move»;
//пример использования функции string.Length
int howManyLetters = enemyText.Length; Vector3:
Я поместил вектор3 к обычным переменным, но на самом деле это структура. Структуры довольно похожи на классы, но в отличии от класса со значениями стурктуры можно работать напрямую, а не через ссылку. Поэтому они частично похожи на переменные. Возможны арифметические операции. Далее структура Vector3 содержит довольно много функций для работы с векторами. Смотрите Unity Documentation для более точного описания. При инициализации вектора3 надо создавать новую инстанцию с помощью new или использовать уже существующий вектор3 (тогда будет созданна его копия). Часто используется для определения местоположения объектов или их скорости и направления движения. Vector3 move;
Vector3 enemyPos = new Vector3 ( 1 , 1 , 0 );
//считывание длинны вектора
float vectorLength = enemyPos.magnitude; Существуют и другие векторы. Например Vector2 или Vector4, но принцип их работы не отличается (кроме многомерности). var:
Это ключевое слово, с помощью которого можно задекларировать переменную без обозначения её типа. Тип переменной будет определен позже в контексте программы. var summe;
float a = 1 ;
float b = 1 ;
//переменная summe получит тип float
summe = a + b;

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. Массивы (статические и динамические):

Массив это упорядочненая структура данных состоящая из элементов одного типа. Массивы могут быть не только одномерными, но и многмерными. Все элементы массива проиндексированны, для целенаправленного доступа к ним. Статический массив имеет определённый размер (количество элементов), который нельзя изменить после декларации. Размер динамического массива можно менять. Индексация массива начинается с 0, то есть первый элемент массива имеет индекс [0].

Spoiler статические массивы:
Так как размер такого массива заранее определен, то скорость работы с таким массивом выше. Поэтому используйте статические массивы, если размер массива заранее известен и будет постоянен. //декларация двумерного массива типа int, состояшего из 2*5 элементов
int [,] numbers = new int [ 2 , 5 ];
//декларация одномерного массива типа GameObject, размер массива определяется через инспектор игрового объекта
public GameObject [] enemy;
//декларация одномерного массива типа string, c его последующей инициализацией
string [] animals = new string [2] < "кот" , "собака" >;
динамические массивы:
Динамические массивы используют класс List. Этот класс находится в пространстве System.Collections.Generic, поэтому лучше присоединить это пространство к скрипту с помощью using System.Collections.Generic;. Динамические массивы позволяют различные действия с размером массива. Можно добавлять, вставлять и удалять элементы. Смотрите MSDN для более точного описания. //присоединение пространства для работы с классом List
using System.Collections.Generic;
//декларация динамического массива типа string
List < string >cars = new List < string >();
//добавление к массиву нового элемента
cars.Add( «Запорожец» );
//вставка нового элемента в массив как первый элемент
cars.Insert(0, «Ауди» );
//удаление элемента «Запорожец»
cars.Remove( «Запорожец» );

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

В С# переменные могут быть с разным уровнем доступа. Уровень доступа определяет возможность обращения к переменной.

Spoiler private:
По умолчанию (если вы никак не обозначили переменную) она получает приватный уровень доступа. Так же этот уровень можно и указать с помощью private. Доступ к таким перменным возможен только внутри их содержащих классов. float speed;
private int score;
public:
Уровень доступа public даёт неограниченный доступ. Например такие переменные можно изменить из других классов. Так же переменная с публичным доступом будет видна в редакторе, это даёт возможность её настройки через инспектор. У компонентов в Юнити публичный уровень доступа. public float speed;
public GameObject player;
protected:
Уровень доступа для базового и наследуемых классов.

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: Арифметические операторы:

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

Spoiler Будьте осторожны при арифметических действиях с разными типами переменных. Если например записать дробный результат в целую переменную, то дробная часть потеряется. float a = 10 ;
float b = 5 ;
float c;
//сложение: c = 10 + 5
c = a + b;
//вычитание: a = 10 — 2
a = a — 2 ;
//деление: b = 8 / 2
b = a / 2 ;
//умножение: с = 10 * 1.5
с = 10 * 1.5 ;
//присвоение: a = 15
a = c;
//инкремент: увеличение а на единицу
a++;
//декремент: уменьшение а на единицу
a—;
//инкремент/декремент: могут стоять до или после переменной, изменяя порядок вычислений

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

В С# есть структура Mathf для различных математических функций. Смотрите Unity Documentation для более точного описания.

Spoiler //функция вернет значение -1, так как проверочный результат отрицательный
float sign = Mathf .Sign (-5);

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

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

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

условные операторы:
Условные операторы позволяют провести сравнение и выполнить определенную часть кода в зависимости от результата.
if . else:
Краткая форма этого условного оператора состоит только из условия и выполняемой части кода, если условие истинно. if (hp isDead = true ;
canFight = false ;
> Полная форма состоит из условия, выполняемой части кода, если условие истинно и выполняемой части кода, если условие ложно. if (hp isDead = true ;
canFight = false ;
> else isDead = false ;
canFight = true ;
> Возможно объединение различных условий в одну конструкцию. if (hp 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. Функции:

Функция это обособленный фрагмент кода для выполнения определенной задачи. Функция может вызываться многократно в тех случаях, когда нужно решить эту задачу. Это позволяет избежать повторения кода. Функции могут быть как сделанные вами индивидуально для достижения ваших целей, так и заготовками от Юнити для стандартных решений. Функции являются частью классов. Функции, как и переменные, имеют различные уровни доступа. К public функциям возможен доступ из других классов, доступ к private функциям возможен только внутри их содержащих классов. Для работы функциям могут понадобиться входные данные — аргументы (функции могут использовать и глобальные переменные их содержащих классов). После своей работы функция может возвращать какой-то результат (используйте Return для возвращения результата). Тип функции должен соответсвовать типу возвращаемого результата. Существуют и функции не возвращающие результат, такие функции имеют тип void.

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 Destroy (gameObject);
>

11. События:

События похожи на функции, только их запуск привязан к различным событиям. Приведу только несколько примеров.

Spoiler void Awake() //это событие вызывается один раз при загрузке скрипта. Обычно используется для инициализации объектов.
void Awake() //C#
> void Start() //это событие вызывается один раз после того, как все void Awake() были выполнены. Используется для инициализации переменных.
void Start() //C#
> void Update() //это событие вызывается заново каждый новый кадр. Обычно содержит основной код для управления игровым объектом.
void Update() //C#
> void LateUpdate() //это событие вызывается заново каждый новый кадр после обработки всех Update(). Обычно используется для управления камерой, чтобы отрисовать уже готовую сцену.
void LateUpdate() //C#
> void FixedUpdate() //это событие вызывается через фиксированный интервал (стандарт 0.02). Используется в расчетах физики (физика не считается в Юнити каждый кадр).
void FixedUpdate() //C#
> OnTriggerEnter2D()
Возможны и другие варианты срабатывания триггера (Enter, Exit, Stay). //это событие вызывается при попадании коллайдера2Д в триггер2Д. Переменная other будет содержать ссылку на попавший в триггер объект.
void OnTriggerEnter2D( Collider2D other) //C#
>

Создание и Использование Скриптов

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

Unity изначально поддерживает три языка программирования:

  • C# (произносится как Си-шарп), стандартный в отрасли язык подобный Java или C++;
  • UnityScript, язык, разработанный специально для использования в Unity по образцу JavaScript;

В дополнение к этим, с Unity могут быть использованы многие другие языки семейства .NET, если они могут компилировать совместимые DLL — см. эту страницу для получения подробностей.

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

Создание скриптов

В отличии от других ассетов, скрипты обычно создаются непосредственно в Unity. Вы можете создать скрипт используя меню Create в левом верхнем углу панели Project или выбрав Assets > Create > C# Script (или JavaScript/Boo скрипт) в главном меню.

Новый скрипт будет создан в папке, которую вы выбрали в панели Project. Имя нового скрипта будет выделено, предлагая вам ввести новое имя.

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

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

После двойного щелчка на скрипте в Unity, он будет открыт в текстовом редакторе. По умолчанию Unity будет использовать MonoDevelop, но вы можете выбрать любой редактор из панели External Tools в настройках Unity.

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

using UnityEngine; using System.Collections; public class MainPlayer : MonoBehaviour < // Use this for initialization void Start () < >// Update is called once per frame void Update () < >> 

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

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

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

A UnityScript script works a bit differently to C# script:

#pragma strict function Start () < >function Update ()

Здесь функции Start и Update имеют такое же значение, но класс не объявлен явно. Предполагается, что скрипт сам по себе определяет класс; он будет неявно производным от MonoBehaviour и получит своё имя от имени файла скриптового ассета.

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

Как было сказано ранее, скрипт определяет только план компонента и, таким образом, никакой его код не будет активирован до тех пор, пока экземпляр скрипта не будет присоединен к игровому объекту. Вы можете прикрепить скрипт перетаскиванием ассета скрипта на игровой объект в панели Hierarchy или через окно Inspector выбранного игрового объекта. Имеется также подменю Scripts в меню Component, которое содержит все скрипты, доступные в проекте, включая те, которые вы создали сами. Экземпляр скрипта выглядит так же, как и другие компоненты в окне Inspector:-

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

// Use this for initialization void Start ()

Debug.Log это команда, которая просто выводит сообщение на консольный вывод Unity. Если вы нажмете сейчас Play, вы увидите сообщение внизу основного окна редактора Unity в окне Console (меню: Window > Console ).

Где скачать скрипты для юнити

Тест по 3ds Max
. интересный бесплатный тест на знание 3ds Max с обучающим эффектом.

За кулисами

Ранго
. о процессе создания мультфильма Ранго, где нет места белому и пушистому, а только грязь и дикие приключения.

Коралина (Coraline) удивительный процесс создания
. все персонажи и окружение было напечатано на 3D-принтере.

Каково работать на украинский Pixar
. работа в большой анимационной студии это всегда приключение и я в него окунулся с головой.

Создание синематика Wrath of the Lich King
. Blizzard всегда поражала своими роликами. Как же они это делают.

Создание удивительного ролика World Builder
. обалденная короткометражка о построении целого города мечты сделана одним человеком.

3d-печать из металла
. стало реальностью напечатать любую вашу 3d-модель из нержавеющей стали, с доставкой по всему миру.

Симуляция

Секреты симуляция одежды
. делюсь своими экспериментами со скоростью и качеством симуляции одежды (тканей) в Marvelous Designer 3.

Симуляция длинных волос
. как я симулил длинные волосы, которые создал плагином HairFarm с помощью ткани в 3ds Max.

Визуализация

Подробно о материалах V-Ray
. очень подробно расписаны основные материалы V-Ray (где и как их лучше использовать, по какому принципу они работают).

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

Моделирование

Как изучать моделирование в 3ds Max, Maya
. для начала нужно определится с терминологией моделирования, понять, что такое правильная топология.

Не используйте операции Boolean (ProBoolean)
. операция Boolean запрещена к использованию во всех цивилизованных странах. Почему так.

Методы симметричного моделирования
. рассмотрено 4 метода, которые сэкономят вам время и нервы при моделировании симметричных моделей.

Текстурирование

Реалистичные микроцарапины на блестящей поверхности
. чтобы новый блестящий материал начал выглядеть более реалистичо, достаточно добавить микропотёртостей.

Как изучать текстурирование в 3ds Max, Maya
. приведен план, следуя которому, вы максимально быстро и эффективно изучите текстурирование.

Уроки 3ds Max

КАК начать изучать 3ds Max или Maya
. есть принципы обучения, которые помогут вам изучить 3D наиболее эффективно.

Правильная структура 3D-проекта
. урок по настройке правильной структуры сцены в 3ds Max, чтобы любой тридешник смог даже через пару лет понять ЧТО вы делали и КАК.

ЧТО ЛУЧШЕ учить Maya или 3ds Max?
. как это ни странно, но выбор 3D-пакета в первую очередь определяется.

Создание двухстороннего материала листьев
. отличный урок для 3ds Max + VRay по созданию материала для просвечивающихся листьев.

В каком порядке изучать 3d?
. от четкого плана (приведен в этой статье) зависит скорость и эффективность изучения любого 3D-пакета.

Для поиска работы по 3d-специальности

Программирование + 3D
. узнайте, можно ли совместить знания программиста и работу в 3D сфере.

Реально ли мне с такимы 3D-навыками найти работу в Киеве?
. ответ на мучительный вопрос для всех начинающих тридешников: «А смогу ли я зарабатывать этим увличением себе на жизнь?».

Работа 3d-аниматором. Где и как научиться анимации
. 3d-анимация — это такая профессия, которой нельзя получить ни в одном государственном ВУЗе. Как же быть.

Расценки на работу моделера, аниматора, визуализатора
. как правильно оценить стоимость своей работы (своего рабочего времени).

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

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