Пользователь
0,0
рейтинг
14 февраля 2014 в 14:40

Разработка → Custom font в Unity3d из песочницы

Как-то при подготовке своего проекта в Unity3d у меня возникла необходимость использовать Bitmap font (он же растровый шрифт). Я очень обрадовался, когда обнаружил в Unity инструменты для создания такого шрифта. Но спустя некоторое время понял, что процедура эта отнюдь нетривиальна из-за отсутствия какой-либо документации на этот счёт.

Эта статья о том, как собрать в Unity готовый к использованию Custom Bitmap Font. Урок довольно подробный и затрагивает работу в Photoshop. Заинтересовавшихся прошу под кат.

Введение

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

Подготовка текстуры

Наш шрифт будет содержать 14 символов: цифры от нуля до девяти, знаки "+", "-", точка, разделяющая дробную и целую части и пробел. Так же оставим парочку резервных мест для символов, которые мы, возможно, захотим добавить в будущем. Итого 16 слотов на текстуре.

Наиболее оптимальным образом расположить эти 16 слотов на текстуре можно таким способом: использовать 4 столбца и 4 строки



Для подготовки примера я использовал Photoshop, и по ходу урока я так же буду давать некоторые пояснения к своим дейсвиям в нём. Итак, открываем редактор изображений и создаём новый документ, размером 400 на 400 пикселей. Рзамер текстуры на данном этапе особо не критичен, главное, чтобы он был не слишком маленьким. Конечный размер текстуры мы выставим уже в Unity в самом конце урока.

Для удобства работы я советую включить отображение линейки, сетки и направляющих (ruler, grid и guides). Хоткей для отображения сетки Ctrl+' для направляющих Ctrl+; для линейки Ctrl+R. Для создания направляющей просто перетащите её с линейкина документ. Настройки всех этих помощников находятся в меню Edit -> Preferences -> Units & Rulers

Далее нам предстоит заполнить текстуру содержанием в виде, собственно, символов. В качестве основы своего растрового шрифта я использовал бесплатный шрифт Unispace. Вызываем инструмент «Text» горячей клавишей Shift+T и вводим наш первый глиф. Все символы должны быть точно позиционированны по центру каждого из 16 слотов (тут нам пригодится вспомогательная сетка). После ввода первого символа (в нашем случае это ноль) жмём Enter для подтверждения ввода. Чтобы правильно позиционировать слой, нажатием клавиш Ctrl+T вызываем инструмент «Transform» и перемещаем слой в нужное место, руководствуясь вспомогательной сеткой.



Проделываем эту нехитрую операцию со всеми нужными нам символами и — вуаля!

Следующим этапом мы объединим все получившиеся слои с цифрами и знаками в один общий слой. Для этого выделим их на панели Layers и нажмём Ctrl+E. Главное случайно не зацепить слой фона, ведь тогда пропадёт вся информация о прозрачности. После этого начинается самая интересная и творческая часть работы. Настраивание эффектов слоя по вкусу. Подробно здесь я не буду её описывать, каждый решит сам, что ему нравится и сделает на свой лад. Что получилось у меня, можно увидеть на картинке ниже.



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

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

Свежепродублированный слой станет основной нашего альфа-канала. Для начала нам надо запечь все его эффекты, то есть растеризовать слой. Для этого я обычно создаю новый пустой слой, выделяю его и слой, с которым я сейчас работаю — и объединяю их в один (Ctrl+E).



У нас получился растеризированный слой с информацией о прозрачности. Теперь осталось только перенести эту информацию в альфа-канал. Для этого, удерживая Ctrl, щелкаем по ионке слоя в панели Layers — получая выделение по маске прозрачности, и, на панели Channels создаём новый канал, опять-таки удерживая Ctrl. Кнопка создания нового канала находится справа внизу панели возле кнопки удаление канала, с корзинкой. Получившийся канал оказался инвертированным — не беда. Комбинацией Ctrl+I восстанавливаем нормальное положение вещей.



Альфа-канал готов. Текстура, в общем-то, тоже. За исключением того, что белый слой фона мешает правильному отображению тени вокруг символов. Я раскрасил его в цвет тени.

Сохраняем текстуру в любимый формат, поддерживающий альфа-канал (я использую TGA-32bit) и переходим к следующему этапу.

Подготовка к созданию шрифта в Unity

Импортируем текстуру в Unity3d. Для этого в панели Project находим папку Assets и из контекстного меню вызываем Import New Asset… Находим файл с нашей текстурой. Готово.



Настройки текстуры довольно очевидны, и я не стану подробно расписывать их. Упомяну лишь, что вам необходимо выставить вменяемый размер текстуры. В нашем случае вполне подойдёт 256x256 px.

Далее в том же контекстном меню создаём новый материал и ассет шрифта (Create -> Material, Create -> Custom Font). В настройках материала выбираем только что импортированную текстуру. Также материал должен поддерживать прозрачность. Поэтому тип материала мы подбираем соответствующий: Transparent/Diffuse.



Наконец, мы подошли к самой сути урока. У нас имеется настроенный материал с красивенькой текстурой, и теперь надо как-то собрать из него готовый к использованию в Unity растровый шрифт.

Растровый шрифт в Unity

По непонятной причине инструмент создания растрового шрифта в Unity сделан крайне неудобно. Впридачу, никакой документации по нему в сети найти не удалось. Всё, что мы имеем, это невнятная панель с настройками:



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

Ascii Start Offset — целое число, отвечающее за сдвиг таблицы Ascii-кода. Пример: устанавливаем значение 10, и теперь доступ к символу «A» с кодом 65 можно получить через код 75.
Kerning — интервал между буквами.
Line Spacing — расстояние между строками текста.
Default Material — материал с текстурой шрифта. Мы его уже создали.
Character Rects — массив настроек маппинга для каждого символа.

Именно Character Rects нам интересней всего.

Size — размер массива (количество символов в шрифте).
Element x — элемент массива Character Rects с настройками конкретного символа.
Index — Ascii-код символа с учётом Ascii Start Offset.
UV — координаты и размеры символа на текстуре.
X, Y, W, H — координаты нижнего левого угла участка текстуры с символом, а так же ширина и высота этого участка.

Здесь необходимо сделать небольшое отступление в теорию маппига, в спойлере имеется краткое наглядное пособие.

Краткая пояснялка в маппинг
Маппинг текстуры — процесс нанесения текстуры на полигональные поверхности в компьютерной графике.



Текстурные координаты участка с цифрой пять будут такими: X = 0.25, Y = 0.5, H = 025, W = 0.25

Vert — координаты и размеры полигона, на который будет маппиться символ
X, Y, W, H — координаты нижнего левого угла полигона с символом, а так же ширина и высота этого полигона. В общем случае x и y выставляем в 0, w и h длина и ширина полигона, причем h отрицательное число. Не спрашивайте, почему, я так сам и не понял.
Width — что-то вроде межбуквенного интервала для конкретного символа.
Flipped — поворачивает текстуру на 90 градусов относительно полигона (может использоваться для вертикальных шрифтов).

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



Как несложно заметить, каждому символу соответствует уникальный Ascii-код. Наприер, код 43 принадлежит знаку плюс. И вот теперь мы приступаем к тяжелой муторной работе по вписыванию координат в соответствующие поля. Ниже дана картинка, на которой показано, как были замапленны знаки плюс и минус.



После того, как все символы будут замапленны, можно поздравить вас с выполнением очень трудной задачи: шрифт готов и теперь его можно использовать!

Создадим в сцене проекта пустой объект. Назначим ему компонент «TextMesh» и выберем в настройках наш шрифт.



Красота!

Послесловие

Создание растровых шрифтов в Unity — очень непростая, но интересная работа. Хочется верить, что, пройдя этот урок, вы узнали для себя что-то новое и полезное. Отсутствие такого описания в своё время сильно тормознуло продвижение моего проекта. И я надеюсь, что этот текст поможет сэкономить кучу времени всем, кому однажды понадобится создать кастомный фонт в Unity.
@fondemzel
карма
15,0
рейтинг 0,0
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Реклама

Самое читаемое Разработка

Комментарии (23)

  • 0
    А TTF хорошо поддерживается?
    • +2
      Да, безо всяких проблем. Реализуется компонентом GUI Text.
      • 0
        только теперь попробуйте натянуть этот текст на объект в сцене как текстуру
  • +1
    NGUI dynamic font + Sci Fi Fonts (http://www.dafont.com/) и будет счастье. Зачем делать лишнюю работу? Я бы не стал использовать битмаповые шрифты по понятным причинам.
    • +2
      Мне эти причины не очень понятны. И причем здесь dynamic font?
      • –2
        кернинг?
        • +2
          При использовании растровых шрифтов в Unity3d текстура каждого глифа накладывается на отдельный квад (четырёхугольник, полигон). При таком раскладе дел нет никаких трудностей настраивать межбуквенный просвет. В уроке это наглядно показано и описано.
          • –2
            только надо делать это руками
            • +2
              Признаться, я совсем не понимаю, куда вы клоните. В настройках Custom Font есть параметр кернига точно такой же, как и в настройках шрифтов TTF. Но даже если бы и не было, разве это повод отказываться от всех преимуществ растровых шрифтов?
    • 0
      Странно, мне тоже не совсем понятно о каких причинах идет речь.
      • 0
        Два слова — локализация и retina.
  • +1
    Интересная статья!
    Я давно откладываю создание автоматического парсера растровых шрифтов из .fnt (Насколько мне известно, это не официальный, но общепринятый формат описания разметки растровых шрифтов и свойств каждой буквы такого шрифта, как расстояние до идущего следующим символа и прочее). Он представляет растровый шрифт как обычный текстурный атлас, но с доп. параметрами. На windows часто используется программа Bitmap Font для создания таких шрифтов и, соответственно, файла описания .fnt
    Мне кажется такой инструмент достаточно востребован и полезен, странно что нет стандартной функции парсинга текстуры из .fnt
    Как я понял, в вашем случае разметка и свойства текста все таки забивается вручную?
    • 0
      Custom Font предлагает настроить такие параметры как кернинг, межстрочный интервал, межзнаковый интервал (наравне с кернингом?), character padding (непонятно, влияет ли он на что-нибудь), ширину символа и непосредственно координаты для маппинга. Последние два задаются вручную для каждого глифа. То есть, при создании шрифта я действительно забиваю все эти параметры вручную. После того, как всё настроено, шрифт готов и не требуется больше никаких изменений. Согласен с вами, было бы очень удобно автоматизировать этот муторный процесс.

      Помимо этих настроек есть еще несколько в компоненте Text Mesh, которые отвечают уже за разметку текста: text anchor, alignment, padding и пр. Этот компонент работает как с растровыми шрифтами, созданными инструментом Custom Font, так и с truetype. Нативная поддержка сторонних растровых шрифтов отсутствует.

      • 0
        Вот как раз .fnt формат содержит всю необходимую информацию для создания Custom Font в Unity3D, там даже с избытком (есть параметры типа XAdvance, которых нет в Unity3D)
        Даже если просто сделать парсер из .fnt (там обчно XML формат, или простой текстовый с переносом строк), уже будет серьезный «прорыв» :)

        Одним из огромных преимуществ TextMesh является то, что (насколько я знаю) сколько бы ни было в нем текста, тратится ровно 1 Draw Call на весь Text Mesh

        В общем Вы меня вдохновили, займусь этим в ближайшее время! :)

        Кстати насчет растровых шрифтов — я не нашел адекватного способа создавать сами шрифты в Windows. На MacOS есть замечательная программа Glyph Designer, где есть такие настройки как обводка, тени (практически полная аналогия со стилями слоев в Photoshop). На Windows я нашел только Bitmap Font, но там нет таких навороченных плюшек. Однако он может брать готовые картинки отдельных символов и паковать их в атлас шрифта со всем необходимым описанием. Но вот этот процесс закидывания отдельных картинок там тоже муторный и совсем не автоматизирован.
        Может вам встречались программы для создания шрифтов с описанием?
        Или вы счастливый обладатель мака? :)
        • +1
          Я только что нашёл удобный инструмент, который очень серьёзно автоматизирует действия по созданию Custom Font! Не знаком с Glyph Designer, но эта утилита вроде бы делает всё тоже весьма неплохо. Ссылка на Unity Asset Store, ссылка на видеообзор.

          В общем-то, мой урок после такой находки можно смело не читать.
          • 0
            Рекомендую обратить внимание на NGUI (в котором есть поддержка AngelCode bitmap font) и Glyph Designer, который этот bitmap font делает наиболее качественно. В качестве альтернативы (для Windows, Linux, Mac) можно попробовать Hiero
          • 0
            У статьи высокая разъяснительная ценность. Часто это важнее ссылок на готовые продукты.
        • 0
          На Windows я нашел только Bitmap Font

          Оно?
          www.angelcode.com/products/bmfont/
          Как вариант — делать полноценный TTF-шрифт (могу посоветовать www.high-logic.com/font-editor/fontcreator.html), а потом через bmfont выкидывать в атлас с нужными настройками растеризации.
          • 0
            Да да, он BMFont оказывается называется.

            Насчет TTF шрифов — слишком круто, часто нужно просто добавить тени, обводку и прочие рюшечки.
            Но посмотреть на FontCreator для ликбеза стоит, спасибо за совет.
            • 0
              Все перечисленные рюшечки с небольшими настройками прекрасно делаются в рантайме в ngui, без необходимости перерисовывать контент в виде шрифта или держать его копию с эффектами в памяти.
  • 0
    С кириллицей и прочим юникодом как быть?
    • 0
      Я так и не смог разобраться с этим вопросом. На ум приходили только абсолютно сумасшедшие варианты, как то мапить русские буквы с английских, которые находятся с ними на одной клавише (L-Д, R-K, Z-Я и etc.).
  • 0
    Еще нужно убрать галочку «Generate Min Maps» в настройках текстуры, с ней координаты разметки неверные

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