В этом уроке мы научимся создавать простую игру на Unity, в которой можно рисовать картины. В этой первой главе мы сделаем большую часть работы по созданию холста, на котором можно рисовать.
В конце у вас получится что-то более или менее похожее на это:
Ну что ж, не будем ждать больше, давайте начнем!
Итак, что же мы будем делать?
Мы будем создавать нечто похожее на классическую видеоигру Microsoft Paint. Хотя она и не похожа на игру, ее основные механики использовались во всех видах игр, будь то мини-игра Warioware, безумное «Утреннее безумие макияжа» Дженни Джао Хсиа, Drawful от Jackbox или рисование лица для пугала в недавней инди-новинке Pikuniku.
В этом уроке мы просто сделаем простую игру по рисованию чьего-то лица. К концу данного туториала у вас должны появиться основы рисования, и, возможно, у вас самих возникнет идея, как можно сделать больше!
Небольшое предисловие: этот учебник предполагает, что вы имеете некоторое представление о том, как работает Unity. В нем также используется код без объяснения основ, поэтому некоторые базовые знания кода будут полезны. Если вы не умеете работать с кодом, но все равно хотите пройти этот урок, я просто напишу весь код, и вам не будет стыдно скопировать его!
Что мы будем делать:
- Настраивать сцену
- Создание второй камеры, которая рисует на текстуру рендера
- Отрисовка этой текстуры на экран
- Создание кистей, которые мы можем использовать для рисования
Настройка сцены
Создайте новый проект Unity, в идеале выбрав вариант 2D шаблона.
Далее нам просто нужно установить сцену для рисования. На чем вы хотите рисовать? Лично я буду рисовать волосы на лице и макияж на лице. Вот изображение, которое я использую для лица. Эту картинку я просто перетащил в сцену и немного повернул. Я также установил цвет фона камеры на #3498db.
Если ваш шаблон проекта не был 2D, возможно, вам также придется изменить настройку Clear flags со Skybox на Solid Color.
Фактическая компоновка не имеет большого значения, это зависит от визуального вкуса. Вы можете просто наложить на него интерфейс MS Paint или оставить все белым и чистым. Если вы чувствуете, что хотите изменить размер или положение камеры, сейчас самое подходящее время сделать это, так как после следующего шага это будет сделать сложнее.
Вторая камера
Камеры Unity обычно просто определяют, на что они направлены, преобразуют увиденное в изображение и показывают его на экране.
К счастью, Unity также позволяет нам взять это изображение и вместо того, чтобы вывести его на экран, использовать его как файл в нашем проекте. Это можно использовать для создания работающих камер безопасности в играх, рисуя то, что видит вторая камера, на экране системы безопасности в вашем игровом мире.
Мы будем использовать их немного нетрадиционным способом, чтобы быстро и эффективно рисовать в нашей игре. У нас будет вторая камера, которая рисует на изображении любые кисти, которые видит, но никогда не стирает старые мазки.
Чтобы убедиться, что все настройки первой камеры идентичны, я бы рекомендовал продублировать первую камеру. Выберите ее в иерархии, затем скопируйте и вставьте. Для наглядности переименуйте ее в «Камера для рисования» или что-то подобное.
Мы хотим, чтобы основная камера и камера для рисования всегда были направлены в одну сторону, и самый простой способ сделать это — сделать камеру для рисования дочерней по отношению к основной камере, для чего перетащите камеру для рисования в основную.
Наконец, у этой камеры Drawing есть компонент Audio Listener, как и у оригинальной камеры. Unity не нравится, когда в сцене присутствует несколько аудиопрослушивателей, поэтому лучше удалить этот компонент.
Вам также понадобится создать необработанное изображение на экране, которое мы будем использовать, чтобы показать, что видит наша Камера рисования. Щелкните правой кнопкой мыши в Иерархии и создайте новое необработанное изображение. Пока оставьте все как есть — белый квадрат в центре экрана.
А теперь немного кода
Далее мы передадим то, что видит эта камера, в текстуру рендеринга. Хотя мы можем сделать этот следующий шаг в редакторе Unity, он имеет тенденцию не работать на разных размерах экрана, если делать это таким образом. Поэтому мы настроим нашу текстуру с помощью кода.
Создайте новый скрипт в вашем проекте и откройте его. Я назвал его DrawingCamera.
using UnityEngine;
using UnityEngine.UI;
public class DrawingCamera : MonoBehaviour
{
public Camera drawingCamera;
public RawImage overlayImage;
void Start() {
drawingCamera.targetTexture = new RenderTexture(Screen.width, Screen.height, 24);
overlayImage.texture = drawingCamera.targetTexture;
}
}
Здесь есть три вещи, которые мы добавили в стандартный скрипт Unity. Давайте разделим их на части.
using UnityEngine.UI;
В зависимости от вашего редактора кода, это можно добавить самостоятельно. Нам нужна эта строка, чтобы сказать: «Этот скрипт использует код Unity UI», который позволяет нам манипулировать созданным нами Raw Image.
public Camera drawingCamera;
public RawImage overlayImage;
Это две переменные, которые мы будем использовать, чтобы знать, где находится наша камера для рисования и необработанное изображение, которое мы создали. Все достаточно просто, нам нужно использовать эти объекты, поэтому мы сохраним их как переменные.
void Start() {
drawingCamera.targetTexture = new RenderTexture(Screen.width, Screen.height, 24);
overlayImage.texture = drawingCamera.targetTexture;
}
Это настоящее мясо нашего скрипта. Когда мы запускаем игру, этот скрипт делает следующее:
- Создает новую текстуру рендеринга, основанную на размере вашего экрана (экрана игры, а не экрана компьютера).
Устанавливает эту текстуру в качестве цели для камеры рисования. Это означает, что камера отрисовки будет рисовать на этой новой текстуре. - Берет наше необработанное изображение и заставляет его рисовать содержимое нашей текстуры рендеринга, что, в свою очередь, является тем, что видит камера.
- С помощью этого сценария наша камера рисования будет рисовать то, что видит, в нашу маленькую белую рамку в центре экрана! Теперь нам просто нужно настроить ее.
Выберите камеру рисования и добавьте к ней этот новый скрипт. Затем установите переменные, которые мы создали, перетащив камеру рисования в поле Камера рисования, а наше необработанное изображение — в поле Наложение изображения.
Если вы запустите свою игру сейчас, белый квадрат будет заменен мини-версией вашей сцены. Она даже реагирует, если вы передвигаете картинки!
Еще несколько настроек
На этом этапе нужно сделать еще две вещи. Во-первых, мы хотим, чтобы наше белое изображение занимало весь экран. Для этого выберите Необработанное изображение, затем в инспекторе вы можете растянуть необработанное изображение, чтобы оно заполнило весь экран, независимо от размера экрана, нажав на изображение Anchor Presets (по умолчанию оно выглядит как квадрат с красным плюсом), удерживая Alt, и нажав на квадрат с горизонтальной и вертикальной синими стрелками в левом нижнем углу.
Наконец, выберите камеру и установите флаги очистки в положение Don’t Clear. Обычно камеры закрашивают все, что они видели в последнем кадре, своим фоновым цветом, поэтому изображение последнего кадра не отображается. Don’t Clear изменяет это, то есть каждый кадр рисуется поверх предыдущего.
Если вы запустите игру сейчас и немного подвигаете лицо, то увидите, что это значит, и, возможно, начнете понимать, как это все работает.
Вот как выглядят последние два шага и конечный результат.
Час кисти
Прежде всего, необработанное изображение будет мешать. Я предпочитаю обходить это, устанавливая в качестве текстуры UIMask, встроенную текстуру, которая просто полностью прозрачна. Наш скрипт заменит ее, когда мы запустим игру, и теперь нам не придется видеть ее во время работы.
Какая игра в рисование без кистей? Мы начнем с простой круглой кисти. Я бы рекомендовал, чтобы она была полностью белой, если это возможно, чтобы мы могли изменить цвет кисти в редакторе Unity. Вы можете взять мою здесь.
Перетащите ее в сцену и задайте ей цвет в инспекторе SpriteRenderer. Мой цвет — #2C3E50. Вы можете перемещать кисть по сцене и получить тот же эффект, что и с лицом, но сейчас мы заставим эффект работать только для наших кистей, используя систему слоев Unity.
Выбрав кисть, вы должны увидеть Layer: Default в правом верхнем углу инспектора. Если вы нажмете на него, у вас появится возможность добавить новый слой. Сделайте это и добавьте слой «Кисти«, затем вернитесь к кисти и установите ее слой на новый.
Затем в нашей камере рисования мы можем ограничить слои, которые она видит, чтобы она видела только слой «Кисти». Щелкните на опции «Обтравочная маска» и выберите «Нет», затем добавьте «Кисти». Теперь при запуске вы получите эффект рисования, но только кистью.
Кисти, которые следуют за мышью
Очевидно, что перемещение головки кисти в инспекторе не будет работать в реальной игре, поэтому мы заставим наши кисти следовать за мышью игрока и быть активными только при нажатой левой кнопке.
Пришло время кода! Это скрипт, заставляющий объект, на который вы его поместите, следовать за мышью и становиться видимым только при нажатой кнопке мыши.
using UnityEngine;
using System.Collections;
public class Brush : MonoBehaviour
{
public SpriteRenderer spriteRenderer;
void Update()
{
Vector3 mousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
mousePos.z = 0f;
gameObject.transform.position = mousePos;
spriteRenderer.enabled = Input.GetMouseButton(0);
}
}
В этом нет ничего слишком дикого, но давайте разберемся.
Vector3 mousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
mousePos.z = 0f;
gameObject.transform.position = mousePos;
Эти три строки определяют положение мыши в пространстве экрана (на каком пикселе экрана находится мышь?).
ScreenToWorldPoint использует основную камеру, чтобы узнать, где находится мышь в пространстве игры. Строка, где мы задаем z равным 0, потому что по умолчанию позиция будет находиться в том же положении z, что и камера, а это означает, что она будет на камере, а не перед ней (не стесняйтесь сократить строку и посмотреть, как это будет выглядеть). Наконец, мы просто устанавливаем объект с помощью этого скрипта в положение мыши.
spriteRenderer.enabled = Input.GetMouseButton(0);
Это удобное однострочное сокращение, которое получает булево значение «true или false» на вопрос «Нажата ли левая кнопка мыши?», и передает это значение в булево значение «должна ли рисоваться графика, true или false?». Таким образом, если мышь удерживается, графика рисуется, а если мышь не удерживается, графика не рисуется.
Код готов! Перейдите в инспектор, поместите этот скрипт на кисть, перетащите графику кисти в поле Sprite Renderer вашего нового скрипта, и готово!
Вот и все, мы разработали игру для рисования в Юнити. В качестве бонуса могу порекомендовать скачать бесплатно Unity ассеты.