Индикатор загрузки при помощи шейдеров
Привет, давайте поговорим о чем-нибудь симпатичном.
Предисловие.
В процессе разработки даже маленьких и простых игр посреди рутинных работ иногда появляются моменты, которые вызывают детский восторг. Собственно, такие моменты и отличают любимое дело (или хобби) от всех остальных.
У меня чаще всего такое происходит, когда понимаешь, как сотворить что-то новое, страшное и до этого момента непонятное. Сразу хочется об этом рассказать всем, кто все еще готов тебя слушать и поделиться, как делятся вкусным куском пиццы.
Поехали.
Мне понадобился индикатор загрузки для длинного подгружаемого списка (список друзей). Уже привычным и естественным жестом для пользователей мобильных является комбинация 1) потянуть резиновый список 2) поглядеть на спиннер 3) в списке появляется новое содержимое.
Индикатор нужен, чтобы пользователь понимал, что что-то происходит и это не конец списка.
В предыдущей игре я использовал простую вращающуюся картинку, но захотелось чего-то интереснее и технологичнее.
Сделаем простой индикатор при помощи шейдеров. Делать будем в Unity, конечно.
Процесс.
Идея простая. Нам нужна прямоугольная прозрачная картинка, на которой появится вращающееся кольцо, у которого начало будет непрозрачным, а конец полностью прозрачным. Примерно такая:
Я взял за основу стандартный шейдер (взять можно здесь: https://unity3d.com/ru/get-unity/download/archive). Выберите в выпадающем меню пункт "Встроенные шейдеры".
Создадим материал, укажем в нем наш новый шейдер и применим его к картинке. (в моем случае, для UI).
Удалил из него все лишнее и оставил только общую структуру.
Над вершинами мы издеваться не будем, только над текстурной частью.
По сути, мы должны описать, каким цветом нужно закрасить каждую точку нашей картинки. В данном случае, нам нужно получить окрашенное кольцо, все остальные точки оставив прозрачными. Напишем что-то такое:
И получим кривое колечко.
Обратите внимание на конструкцию lerp(a, b, step (c, X)). Она часто встречается в шейдерах и является заменой условного выражения. Читается как: “Если X >= с, тогда b, иначе a”.
Можете почитать о ней подробнее тут (https://shadowmint.gitbooks.io/unity-material-shaders/conten...).
Теперь сосредоточимся на получении нужного нам эффекта вращения.
Будем изменять значение полупрозрачности в зависимости от угла:
И получим что-то такое:
Отмечу, что функция frac() возвращает часть числа после запятой. С отрицательными значениями может работать странно, кажется, у меня была такая проблема.
А еще мы определили число Пи.
Ну и под конец - немного магии. Добавим прямо в шейдер влияние времени:
Про _Time в шейдерах можете почитать в мануалах (https://docs.unity3d.com/Manual/SL-UnityShaderVariables.html). Отмечу только, что я использовал _Time.y - это время в масштабе 1:1, прошедшее с запуска игры.
Для финализации результата я еще немного сгладил края и... “голову” кольца.
Ссылка на полный код в конце.
В игре получилось так (там добавлено немного свечения):
Заключение.
Ребятам, кто начинает - экспериментируйте.
Ребятам, кто разбирается - поправляйте!
Всем спасибо. Делайте хорошие игры.
P.S.
Конечный результат (немного сбилась табуляция, ну да ладно) - (https://github.com/imetelyov/unity-loading-ring-shader/blob/...)
Мои скромные поделки можете глянуть тут: https://vk.com/quasar.games





