Как назначить камеру главной в unity. Уменьшение числа Draw Calls. Настройка параметров текстуры

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


Подготовка персонажа:

По умолчанию, "лицо" персонажа, должно смотреть вправо, при условии отсутствия вращения объекта.

Подготовка карты:
Чтобы установить границы, внутри которых может двигаться камера. Для этого просто добавляем на сцену обычный спрайт-квадрат, назовем его Bounds Map (не забываем указать этот объект в поле скрипта), ставим по центру карты и увеличиваем до нужного размера. После настройки, делаем его невидимым, чтобы не мешал.

Using UnityEngine; using System.Collections; public class Camera2DFollowTDS: MonoBehaviour { private enum Mode {Player, Cursor}; private Mode face; // вектор смещения, относительно "лица" персонажа или положения курсора private float smooth = 2.5f; // сглаживание при следовании за персонажем private float offset; // значение смещения (отключить = 0) private SpriteRenderer boundsMap; // спрайт, в рамках которого будет перемещаться камера private bool useBounds = true; // использовать или нет, границы для камеры private Transform player; private Vector3 min, max, direction; private static Camera2DFollowTDS _use; private Camera cam; public static Camera2DFollowTDS use { get{ return _use; } } void Awake() { _use = this; cam = GetComponent(); cam.orthographic = true; FindPlayer(); CalculateBounds(); } // переключатель, для использования из другого класса public void UseCameraBounds(bool value) { useBounds = value; } // найти персонажа, если он был уничтожен, а потом возрожден // для вызова из другого класса, пишем: Camera2DFollowTDS.use.FindPlayer(); public void FindPlayer() { player = GameObject.FindGameObjectWithTag("Player").transform; if(player) transform.position = new Vector3(player.position.x, player.position.y, transform.position.z); } // если в процессе игры, было изменено разрешение экрана // или параметр "Orthographic Size", то следует сделать вызов данной функции повторно public void CalculateBounds() { if(boundsMap == null) return; Bounds bounds = Camera2DBounds(); min = bounds.max + boundsMap.bounds.min; max = bounds.min + boundsMap.bounds.max; } Bounds Camera2DBounds() { float height = cam.orthographicSize * 2; return new Bounds(Vector3.zero, new Vector3(height * cam.aspect, height, 0)); } Vector3 MoveInside(Vector3 current, Vector3 pMin, Vector3 pMax) { if(!useBounds || boundsMap == null) return current; current = Vector3.Max(current, pMin); current = Vector3.Min(current, pMax); return current; } Vector3 Mouse() { Vector3 mouse = Input.mousePosition; mouse.z = -transform.position.z; return cam.ScreenToWorldPoint(mouse); } void Follow() { if(face == Mode.Player) direction = player.right; else direction = (Mouse() - player.position).normalized; Vector3 position = player.position + direction * offset; position.z = transform.position.z; position = MoveInside(position, new Vector3(min.x, min.y, position.z), new Vector3(max.x, max.y, position.z)); transform.position = Vector3.Lerp(transform.position, position, smooth * Time.deltaTime); } void LateUpdate() { if(player) { Follow(); } } }
Вот и всё. Убедитесь что у персонажа установлен стандартный тег Player. Внимание. Если установлены границы перемещения, то они будут действовать только для камеры, на самого персонажа это никак не повлияет.

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

Свойства

Свойство: Функция:
Clear Flags Определяет, какие части экрана будут очищены. Это удобно при использовании нескольких камер для отрисовки разных элементов игры.
Background Цвет, применяемый для фона после отрисовки всех элементов, в случае отсутствия скайбокса.
###Маска отрезания Включение или исключение слоёв объектов на рендер этой камерой. Назначение слоёв объектам производится через Inspector.
Projection Переключает способность камеры симулировать перспективу.
X Камера будет рисовать объекты в перспективе.
X Camera will render objects uniformly, with no sense of perspective. NOTE: Deferred rendering is not supported in Orthographic mode. Forward rendering is always used.
Size (когда выбран ортографический режим) Размер зоны видимости камеры для ортографического режима.
Field of view (когда выбран режим перспективы) Ширина угла обзора камеры, измеряется в градусах по локальной оси Y.
###Clip Planes (Плоскости отреза) Дистанция, на которой камера начинает и заканчивает рендеринг.
X Ближайшая точка относительно камеры, которая будет рисоваться.
X Дальняя точка относительно камеры, которая будет рисоваться.
Normalized View Port Rect Четыре значения, отражающие то, в какой области экрана будет выведено изображение с камеры, в экранных координатах (от 0 до 1).
X Начальная позиция области по горизонтали вида камеры, который будет рисоваться.
Y Начальная позиция области по вертикали, где вид камеры будет рисоваться.
W (Ширина) Ширина вида камеры на экране.
H (Высота) Высота вида камеры на экране.
Depth Позиция камеры в очереди отрисовки. Камеры с большим значением будут нарисованы поверх камер с меньшим значением.
###Способ рендера Опции для определения методов рендеринга для камеры.
X Камера использует метод рендеринга, установленный в Player Settings.
Вершинное освещение Все объекты рисующиеся этой камерой будут рендериться как Vertex-Lit-объекты.
X Все объекты будут рендериться с одним проходом на материал.
Deferred Lighting (только в Unity Pro) Все объекты будут рендериться сначала без освещения, а затем будет произведён рендер освещения для всех объектов разом, в конце очереди рендеринга.
Target Texture Ссылка на Render Texture , которая будет содержать результат рендеринга камеры. Назначение этой ссылки отключает способность камеры рендерить на экран.
HDR Включение технологии High Dynamic Range.
Target Display Defines which external device to render to. Between 1 and 8.

Детали

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

Вы можете создать несколько камер и назначить каждой свою глубину(Depth). Камеры будут отрисовываться от низшей глубины до высшей глубины. Другими словами, камера с Depth 2 будет отрисована поверх камеры с Depth 1. Вы можете настроить значение свойства Normalized View Port Rectangle для изменения позиции и размера изображения с камеры на экране, например для создания нескольких экранов в одном, или для создания зеркала заднего вида.

Способ рендера

Unity поддерживает различные способы рендеринга. Вы должны выбрать один из них, в зависимости от содержимого вашей игры и целевой платформы / аппаратного обеспечения. Различные методы рендеринга поддерживают различные возможности и дают различную производительность, особенно в аспекте применения теней и источников света. Метод рендеринга, используемый в вашем проекте, выбирается в Player Settings. Дополнительно свой метод рендеринга может быть выбран для каждой камеры.

Solid color

Любые пустые части экрана будут отображать текущий фоновый цвет (Background Color ) камеры.

Только глубина

Если вы хотите рисовать оружие игрока не подвергая его обрезке объектами окружения, внутри которых оно находится, установите одну камеру, рисующей окружение, с Depth 0, и ещё одну камеру, рисующую оружие - Depth 1. Для камеры оружия выберите Clear Flags depth only . Это позволит отобразить окружение на экране, но проигнорировать всю информацию о взаимном положении предметов в пространстве. Когда оружие будет отрисовано, непрозрачные части будут полностью отрисованы на экране поверх ранее находившегося там изображения, независимо от того, насколько близко оружие находится к стене.


Не очищать

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

Clip Planes (Плоскости отреза)

Near и Far Clip Plane - свойства, определяющие, где начинается и заканчивается область отрисовки камеры. Эта область ограничивается плоскостями, перпендикулярными направлению камеры, и находившимися в этих позициях относительно неё. Near Plane - это ближайшая позиция, а Far Plane - дальняя позиция.

Плоскости также определяют точность буфера глубины. Для обеспечения наивысшей точности вам следует отодвинуть Near Plane так далеко, насколько возможно.

Обратите внимание, что эти плоскости вместе определяют поле зрения камеры, которое известно как фрустум . Unity гарантирует, что объекты, полностью находящиеся за пределами фрустума, не будут отображаться. Это называется Frustum Culling и это срабатывает независимо от Occlusion Culling.

Из соображений производительности вы можете прекращать отрисовку мелких объектов раньше, чем отрисовку прочих. Для этого поместите их в separate layer и настройте дистанцию обрезки для этого слоя, используя функцию Camera.layerCullDistances .

Маска отрезания

Culling Mask используется для выборочного рендеринга групп объектов посредством использования слоёв. Больше информации об использовании слоёв можно найти .

Normalized Viewport Rectangles

Normalized Viewport Rectangles предназначено для определения части экрана, на которой будет отрисовано изображение с камеры. Вы можете, к примеру, вставить изображение карты в нижний правый угол экрана, а вид с камеры на выпущенной ракете - в верхний левый угол. Немного поработав над дизайном, используя Viewport Rectangle , вы сможете создать кое-какие уникальные системы.

Очень просто создать раздельный экран для двух игроков, используя Normalized Viewport Rectangle . После создания двух камер, установите обеим камерам свойство H в значение 0.5 и для одной из них свойство Y в значение 0.5, а для другой - в значение 0. В результате, первая камера будет рисовать изображение в верхней половине экрана, а вторая камера - в нижней половине экрана.


Orthographic

Переключив камеру в ортографичесий (Orthographic ) режим, вы устраните всю перспективу из отрисовываемого ей изображения. Это полезно для создания двумерных и изометрических игр.

Заметьте, что туман отрисовывается при этом равномерно, так что может выглядеть не так, как вы ожидали. Прочтите справко по компоненту Render Settings для получения подробностей.



Текстура рендера

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


Target display

A camera has up to 8 target display settings. The camera can be controlled to render to one of up to 8 monitors. This is supported only on PC, Mac and Linux. In Game View the chosen display in the Camera Inspector will be shown.

  • Камеры могут быть вызваны, назначены дочерним объектом и заскриптованы как любой другой игровой объект
  • Для эффекта ускорения в гоночной игры используйте повышенный Field of View .
  • Камеры можно использовать в симуляции физики, если к ним добавить компонент Rigidbody .
  • Нет ограничения на количество камер в сцене.
  • Ортографические камеры отлично подходят для создания 3D пользовательских интерфейсов
  • Если вы наблюдаете артефакты глубины (мелькают близкорасположенные поверхности), попробуйте выставить Near Plane в максимально возможное значение.
  • Камеры не могут рендерить одновременно на экран и в Render Texture, только в одно из них.
  • Pro-лицензия предоставляет функцию названную Render-to-Texture, которая позволяет рендерить камеру в текстуру, для еще более уникальных эффектов.
  • Unity поставляется с предустановленными скриптами для управления камерой, их можно найти в Components->Camera Control . Поэкспериментируйте с ними чтобы узнать об их возможностях.

Справочник по камерам

С его мощной поддержкой редактора. Судьба сложилась так, что я не мог его тогда купить, да и пробной версии не было. В итоге, мне пришлось самому написать несколько полезных скриптов для реализации 2d на Unity3d . О том, как это сделать, пойдет речь в этой статье.

Источники информации

Сразу напишу о некоторых полезных источниках информации по Unity3d для тех, кто вообще не знаком с движком, либо только начинает с ним знакомиться.
  • Unity3d.com – официальный сайт движка. Здесь полезными будут странички:
    • Unity User Manual – официальное руководство пользователя. Начинать изучать здесь.
    • Unity Reference Manual – более углубленное изучение.
    • Scripting Reference – здесь все по библиотеке Unity3d для всех трех поддерживаемых языков (Boo, JavaScript и C#).
    • – здесь можно найти видео-руководства, примеры, презентации.
    • Unity Answers – здесь ответят на ваши вопросы, либо можно найти готовый ответ. Часто пользовался этим ресурсом.
    • Unity Community - форум.
  • Unity3d по-русски - сайт разработчиков под Unity3d на русском языке. Если у вас неважно с английским, здесь есть руководства на русском, а на форуме можно получить ответы на интересующие вопросы.
  • Unity3d Wiki – очень полезный ресурс. Здесь множество рекомендаций, бесплатных полезных скриптов.
Также после установки Unity3d на вашем компьютере появятся локальные версии руководств и видео. При первом запуске их можно будет выбрать из окна приветствия или найти в меню Help .

Что понадобится

Версия используемого движка – 3.3, весь код написан на C# и будет работать на всех лицензиях Unity. Достаточно скачать бесплатную версию Unity . В комплекте идет MonoDevelop бесплатная среда для разработки на.NET (на случай, если у вас нет Visual Studio ). Среда легко настраивается «под себя», в ней есть все, что необходимо для разработки, поддерживает такие удобные функции, как автодополнение, шаблоны подстановки кода и многое другое. Сам я пользуюсь Visual Studio в связке с Resharper – так удобнее. Редактор Unity поддерживает обе среды.

Условия использования кода

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

Условие только одно : при использовании кода (в том числе модифицированного) в коммерческом проекте необходимо указать ссылку на автора (т.е. - меня).

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

Настройка камеры

Для начала создайте пустую сцену без объектов. Удалите объект MainCamera , добавленный по умолчанию.

Нужно настроить камеру так, чтобы она стала «пригодна» для 2d. В Unity под камерой понимается класс Camera . Для того, чтобы ее использовать, нужно:

  1. Создать пустой объект (GameObject -> Create Empty ).
  2. Выбрать его и добавить ему компонент Camera (Component -> Rendering -> Camera ).
Изначально камера перпендикулярна плоскости XOY и направлена вдоль оси Z в положительном направлении. В дальнейшем для простоты спрайты будут лежать в плоскости XOY и по направлению к камере, так что поместите камеру в центр координат и отдалите ее по оси Z на необходимое расстояние в отрицательное полупространство (скажем, в точку ).

Для 2d-графики положение спрайтов в пространстве не важно. На много важнее, как спрайты друг друга перекрывают. Камера поддерживает два режима (вида проекции): перспективный (Perspective ) и ортогональный (Orthographic ). Первый используется во всех 3d-играх: объекты, расположенные дальше от камеры, выглядят меньше. Это почти то, как мы видим наш мир. Нам нужен второй режим, Orthographic – объекты всегда рисуются реального размера и перекрывают друг друга в зависимости от расстояния до камеры. Идеальный режим камеры для 2d и изометрии. В окне Inspector в компоненте Camera вновь созданного объекта в поле Projection выберите Orthographic . При этом некоторые параметры (соответствующие Perspective -режиму) пропадут, но появится параметр Size – размер ортогональной камеры.

Теперь настроим камеру так, чтобы каждый пиксель на экране соответствовал одной единице (unit) пространства в Unity. В дальнейшем это будет удобно при перемещении спрайтов и задании их размеров в пикселях. Для этого размер ортогональной камеры (параметр Size ) должен равняться половине высоты экрана в пикселях. Например, если это экран iPhone 3G в портретном режиме, разрешение экрана которого 320x480, то Size = h/2 = 480/2 = 240 .

Для того чтобы каждый раз не делать всего этого вручную, напишем скрипт:
using UnityEngine; internal class Ortho2dCamera: MonoBehaviour { private bool uniform = true; private bool autoSetUniform = false; private void Awake() { camera.orthographic = true; if (uniform) SetUniform(); } private void LateUpdate() { if (autoSetUniform && uniform) SetUniform(); } private void SetUniform() { float orthographicSize = camera.pixelHeight/2; if (orthographicSize != camera.orthographicSize) camera.orthographicSize = orthographicSize; } }
Если добавить этот скрипт на любой игровой объект (GameObject ), то:

  1. Автоматически этому объекту добавится компонент Camera . За это отвечает атрибут RequireComponent .
  2. Выполнится функция Awake . За это отвечает атрибут ExecuteInEditMode , который заставляет выполняться скрипты прямо в редакторе.
  3. В результате вызова этой функции камера станет ортогональной.
  4. Ее размер будет установлен таким, чтобы один пиксель на экране соответствовал одной единице Unity (вызов функции SetUniform ). Это будет выполняться автоматически для любого экрана.
Теперь камера должна выглядеть так:

Улучшения

  1. Если размер экрана может меняться во время выполнения (поворот экрана смартфона, смена разрешения пользователем), неплохо бы автоматически менять размер камеры. Это можно делать в функции LateUpdate .
  2. Если освещение использоваться не будет (как и бывает в большинстве 2d-игр), рекомендую в настройках проекта (File->Build Settings->Player Settings->Other Settings ) установить параметр Rendering Path в значение Vertex Lit . Это самый простой способ отрисовки объектов (каждый объект за один шаг для всех источников света), поддерживаемый большинством устройств. В моем случае для iOS-устройств это дало скачок в производительности. То же самое можно сделать для конкретной камеры. По умолчанию камера используют значение из Player Settings .

Спрайт

Спрайт - прямоугольник с наложенной на него текстурой. Договоримся, что он по умолчанию будет расположен в плоскости XOY. Тогда за взаимное расположение спрайтов (слои) будет отвечать координата Z.

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

Спрайт будет задаваться несколькими параметрами:
private Vector2 size = Vector2.one; private Vector2 zero = Vector2.one / 2; private Rect textureCoords = Rect.MinMaxRect(0, 0, 1, 1); private bool pixelCorrect = true;
Расшифруем их:
Для отображения прямоугольника будем использовать объект класса Mesh . В самом простом случае он инициализируется:

  1. списком вершин,
  2. списком индексов вершин, составляющих вершины треугольников, из которых состоит прямоугольник,
  3. списком соответствующих вершинам текстурных координат.
Учитывая параметры спрайта указанные выше, объект класса Mesh будем создавать так:

Private static Mesh CreateMesh(Vector2 size, Vector2 zero, Rect textureCoords) { var vertices = new { new Vector3(0, 0, 0), // 1 ___ 2 new Vector3(0, size.y, 0), // | | new Vector3(size.x, size.y, 0),// | | new Vector3(size.x, 0, 0) // 0 ---- 3 }; Vector3 shift = Vector2.Scale(zero, size); for (int i = 0; i < vertices.Length; i++) { vertices[i] -= shift; } var uv = new { new Vector2(textureCoords.xMin, 1 - textureCoords.yMax), new Vector2(textureCoords.xMin, 1 - textureCoords.yMin), new Vector2(textureCoords.xMax, 1 - textureCoords.yMin), new Vector2(textureCoords.xMax, 1 - textureCoords.yMax) }; var triangles = new { 0, 1, 2, 0, 2, 3 }; return new Mesh { vertices = vertices, uv = uv, triangles = triangles }; }
Чтобы нарисовать меш, понадобятся компоненты MeshRenderer и MeshFilter . Первый компонент содержит ссылки на материалы текстур для спрайта. Второй из них содержит объект MeshFilter.mesh , который он и рисует. Для изменения спрайта нужно, соответственно, изменять этот объект. Сам спрайт реализуется через компонент SampleSprite . Для того чтобы у спрайта эти два компонента были всегда, добавим ему соответствующие атрибуты RequireComponent :

Using UnityEngine; public class SampleSprite: MonoBehaviour { … }
Атрибут AddComponentMenu добавляет в меню Component редактора пункт Sprites->Sample Sprite . Используя его можно добавить к любому объекту Unity наш компонент SampleSprite .

Для того чтобы можно было видеть спрайт во время редактирования, атрибут ExecuteInEditMode позволяет вызывать функции Awake и Start класса SampleSprite прямо в редакторе. Внутри этих функций создается меш:

Private MeshFilter meshFilter; private MeshRenderer meshRenderer; #region Unity messages // Use this for initialization private void Awake() { meshFilter = GetComponent(); meshRenderer = GetComponent(); } private void Start() { // NOTE: initializing mesh here because our camera is initialized in Awake() InitializeMesh(); } #endregion
При инициализации меша нужно учитывать флаг pixelCorrect . Проверяем, во сколько раз высота экрана отличается от размера камеры - во столько раз нужно увеличить меш, учитывая, что при нормальном варианте (высота экрана равна удвоенному размеру ортогональной камеры) размер меша равен размеру области текстуры для спрайта:

Private void InitializeMesh() { Camera cam = Camera.main; if (pixelCorrect && cam != null) { float ratio = cam.pixelHeight / (2 * cam.orthographicSize); size.x = NonNormalizedTextureCoords.width * ratio; size.y = NonNormalizedTextureCoords.height * ratio; } meshFilter.mesh = CreateMesh(size, zero, textureCoords); }
NonNormalizedTextureCoords – текстурные координаты в пикселях. Определяются через нормализованные текстурные координаты (параметр спрайта) и размер самой текстуры TextureSize :

Private Rect NonNormalizedTextureCoords { get { Rect coords = textureCoords; Vector2 texSize = TextureSize; if (texSize != Vector2.zero) { coords.xMin *= texSize.x; coords.xMax *= texSize.x; coords.yMin *= texSize.y; coords.yMax *= texSize.y; } return coords; } } private Vector2 TextureSize { get { if (meshRenderer == null) return Vector2.zero; Material mat = meshRenderer.sharedMaterial; if (mat == null) return Vector2.zero; Texture tex = mat.mainTexture; if (tex == null) return Vector2.zero; return new Vector2(tex.width, tex.height); } }
Заметьте, что меш инициализируется в функции Start , потому что при его инициализации используется информация из камеры, а она инициализируется нами в Awake , т.е. в Start такая информация уже доступна для других объектов (в Unity сначала вызываются все Awake , затем все Start , но порядок вызова одной и той же функции для различных объектов не определён). Так же в этом примере используется Camera.main - главная камера на сцене. Т.е. наша камера должна быть помечена тегом MainCamera .

В принципе, на этом этапе со спрайтом уже можно работать. Для этого к любому объекту нужно прикрепить компонент SampleSprite (например, через меню Component или перетянув на него файл скрипта). Автоматически к нему добавятся компоненты MeshFilter и MeshRenderer . Теперь если перетянуть на этот объект материал текстуры (или текстуру, а материал создастся автоматически), и настроить параметры, то можно будет увидеть готовое 2d-изображение.

Настройка параметров текстуры

Для правильного отображения спрайта необходимо в свойствах текстуры изменить следующие параметры:
  1. чтобы движение спрайта было плавным, чтобы при изменении размеров спрайт выглядел сглаженным, необходимо параметр экспорта текстуры Filter Mode установить в Bilinear или Trilinear );
  2. установите Texture Type в значение GUI ;
  3. не забудьте убрать компрессию, установив значение параметра Format в Truecolor .

Освещение

Обычно в 2d-играх не используется освещение. Эти эффекты задаются заранее художниками на текстурах, системой частиц и другими способами. К тому же освещение влияет на скорость отрисовки. Поэтому в случае спрайтов для используемых материалов необходимо выбрать соответствующий шейдер:
  1. В версии 3.3 есть группа шейдеров Unlit с отключенным освещением. Для спрайтов с прозрачностью подойдет шейдер Unlit->Transparent , для заднего фона Unlit->Texture .
  2. В старых версиях Unity можно использовать шейдер Transparent->Diffuse . Но тогда надо не забыть в Edit->Render Settings проставить Ambient Light в белый, чтобы все спрайты были натурального цвета. Иначе они будут затемненными, потому что по умолчанию в качестве Ambient Light стоит оттенок серого.
  3. Можно написать свой шейдер, в котором освещение будет отключено. О том, как это сделать, можно посмотреть в официальном пособии по шейдерам Unity .

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

Unity позволяет расширить возможности редактора. Для этого используются, например:
  1. Тег EditorOnly .
  2. Создание редакторов игровых объектов в Инспекторе Компонентов путем наследования от класса Editor .
  3. Создание окон редактора путем наследования от класса EditorWindow .
Можно предоставить пользователю возможность задавать некоторые параметры спрайта в более удобных единицах и тут же видеть результат. Например, нулевую точку лучше всего хранить нормализованной, т.к. если размер объекта на текстуре изменится, то ее не нужно будет исправлять ручками. Но задавать ее в редакторе удобнее в пикселях, чтобы представлять, как она будет расположена относительно размеров спрайта. Для всех этих нужд подойдет вот такая реализация класса Editor :

Using UnityEditor; using UnityEngine; public class SampleSpriteEditor: Editor { public override void OnInspectorGUI() { Target.Size = EditorGUILayout.Vector2Field("Size", Target.Size); Target.Zero = EditorGUILayout.Vector2Field("Zero Point", Target.Zero); Target.TextureCoords = EditorGUILayout.RectField("Texture Coordinates", Target.TextureCoords); Target.PixelCorrect = EditorGUILayout.Toggle("Pixel Correct", Target.PixelCorrect); if (GUI.changed) { Target.UpdateMesh(); EditorUtility.SetDirty(target); } } private SampleSprite Target { get { return target as SampleSprite; } } private static void CreateSprite() { var gameObject = new GameObject("New Sample Sprite"); gameObject.AddComponent(); Selection.activeObject = gameObject; } } Внимание : все скрипты, связанные с редактором, должны располагаться в папке Assets/Editor .

Редактируемые параметры добавим в класс SampleSprite и сделаем их условно-компилируемыми (чтобы этот код не попал в конечный продукт, а работал только в редакторе):

#if UNITY_EDITOR public Vector2 Size { get { return size; } set { size = value; } } public Vector2 Zero { get { return Vector2.Scale(zero, size); } set { if (size.x != 0 && size.y != 0) { zero = new Vector2(value.x / size.x, value.y / size.y); } } } public Rect TextureCoords { get { return NonNormalizedTextureCoords; } set { textureCoords = value; Vector2 texSize = TextureSize; if (texSize != Vector2.zero) { textureCoords.xMin /= texSize.x; textureCoords.xMax /= texSize.x; textureCoords.yMin /= texSize.y; textureCoords.yMax /= texSize.y; } } } public bool PixelCorrect { get { return pixelCorrect; } set { pixelCorrect = value; } } public void UpdateMesh() { InitializeMesh(); } #endif
В данном случае параметр Zero измеряется в тех же единицах, что и size , а TextureCoords – в пикселях текстуры.

Оптимизация, улучшения и прочее

Уменьшение числа Draw Calls

Есть несколько способов это сделать.
  1. Static batching . Если объект никогда не изменяется, то его можно пометить как статический (галочка Static в Инспекторе ). Все такие объекты будут объединены в один большой и будут рисоваться за один Draw Call. К сожалению, функция static batching доступна только в Pro-версии Unity.
  2. Dynamic batching . Если несколько объектов используют один и тот же материал, Unity перед отрисовкой объединяет их в один, и все они будут рисоваться за один Draw Call. Для достижения этого эффекта текстуры необходимо объединять в атлас – одну большую текстуру. Используйте атласы – они позволяют сократить как количество Draw Call (за счет dynamic batching ), так и объем памяти, занимаемой текстурами (что очень актуально для мобильных платформ).
    Подсказка : включение/отключение видов batching для некоторых платформ осуществляется в File->Build Settings->Player Settings .
  3. Менеджер спрайтов. Одна из реализаций – SpriteManager . Спрайт добавляется в менеджер спрайтов, который использует одну текстуру-атлас (в компоненте MeshRenderer ), и создает для спрайтов меш (в компоненте MeshFilter ), состоящий из множества прямоугольников, по одному для каждого спрайта (к этой реализации автор прикрутил удобство редактора и получил SM2 ). Также улучшить менеджер спрайтов можно за счет задания спрайту ссылки на используемый материал, все материалы хранить в компоненте MeshRenderer менеджера спрайтов, а меш рисовать как совокупность более маленьких мешей (по одному на материал), пользуясь возможностями