Всем привет, меня зовут Григорий Дядиченко, и я обожаю VFX. В данной статье хочется больше поговорить про VFX Graph, про его функции и про то, как там можно сделать простенькие вихри (разными способами). Если вам интересна тема Unity и VFX, добро пожаловать под кат.

Сразу скажу, что эта статья скорее про работу с VFX Graph, чем про создание самого по себе вихря. С двух точек зрения. Если вам нужно сделать красивое торнадо, есть способы оптимальнее и лучше. Как пример один способ описывается тут и он часто будет оптимальнее, проще и эффектнее. С другой стороны, я не буду разбирать «симуляцию вихря», уравнения Навье-Стокса или циркуляционную теорему Кельвина. Мы будем разбирать, как сделать эффект похожий на вихрь, какие инструменты есть для этого в VFX Graph и т.п. Подобная работа с частицами может скорее дополнить эффект из видео выше, или сделать через частицы воздействие на окружение подобных торнадо. Ну для начала покажем что получилось.
Подготовка графа
В отличии от Shuriken в VFX Graph эммитеры по форме не выравнивают скорость по этой форме. Если мы хотим сделать аля торнадо, первое что нам нужно сделать — это эммитер в виде конуса. Такой в VFX Graph есть.

Также заменив стандартные партиклы на более мягкие и увеличив число частиц получится примерно такой эффект. Для удобства нам так же понадобится контролировать угол нашего вихря и высоту. Можно это конечно делать напрямую через радиусы и параметры конуса, но угол является более понятной метрикой.
Конус в сущности представляет из себя «закрученный» треугольник. Если разобрать треугольник, то в нашем случае он состоит из Top Raduis и Height. При этом из математики известно, что тангенс угла равен отношению противолежащей стороны к прилежащей в прямоугольном треугольнике. Так как задавать нам нужно высоту и угол, то осталось найти Top Radius. На рисунке ниже можно посмотреть расчёт.

То есть радиус равен тангенс угла при основании, умноженный на высоту. Давайте перенесём это всё в VFX Graph.

Так как углы привычнее задавать в градусах, а не в радианах, а в тангенсе угол в радианах, то сначала мы переводим градусы в радианы по формуле:
Но так как мне удобнее использовать общий угол из основания конуса, то мы делим его на 2 или вместо 180 делим на 360. Всё вынесено в графе в внешние параметры для удобства контроля, теперь мы можем регулировать наш конус углом и высотой.
Так же в VFX Graph мы можем контролировать спавн частиц. В целом чтобы при изменении высоты и угла не менялась (до определённого предела) плотность частиц вихря, нам нужно изменять рейт спавна в зависимости от параметров. Так как я хочу, чтобы частицы были на боковой поверхности конуса, логично использовать за некий параметр использовать площадь боковой поверхности конуса. Формула прощади боковой поверхности конуса:

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

Итак, со спавном мы вроде разобрались. Да, стоит сказать что математика выше подходит чтобы получить равномерное распределение частиц на поверхности конуса. Для распределения частиц в объёме нужна формула объёма. То, что частицы спавнятся на поверхности задаётся в настройках Set Position (Shape: Arc Cone). И дополнительная константа в графе и параметр Rate нужны просто для удобства.
Путь 1. Касательная к окружности
Пора начать разбираться со скоростями. Первая идея, что мне пришла в голову, чтобы получить нужный эффект. Касательная к окружности конуса. Если посмотреть на конус сверху, то это просто серия вложенных окружностей. Мы всегда можем узнать позицию частицы в VFX Graph с помощью Get Attribute: position, а дальше всё дело техники. Так как у нас локальная система координат, то нужная нам касательная к окружности — это нормаль к радиусу. Нормаль в нашем случае представляет из себя:
Так как мы находимся в плоскости XZ. Но в локальной системе координат мы возьмём ещё за упрощения, что все частицы вращаются вокруг оси (0, 0). Так что dx = x — 0 = x, где x — позиция конкретной частицы. То есть:
Что в графе превратится в

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

Путь 2. Вращение частиц
Чтож, так не получилось. Давайте попробуем что-нибудь другое. Тут я пожалуй сразу покажу граф целиком, а потом объясню, что он делает и почему:

Выглядит этот вихрь уже вот так:
Идея такова, что мы работаем теперь не в скоростях, а в позиция. У нас есть центральная ось и вокруг неё в плоскости XZ мы вращаем частицы. Поэтому важно, что теперь задаётся позиция, а не скорость. Скорость зависит от радиуса окружности, чтобы частицы двигались быстрее, если они находятся на большей орбите + добавлен небольшой рандом для более «натурального» эффекта. Верхняя часть с эммишеном частиц никак не изменилась, по сути мы изменили только принцип движения. Визуально в целом неплохо и можно менять скорость, при этом ни одна частица не уйдёт с орбиты. Но потом я решил добавить ещё одну функцию «наклон орбит» и граф стал таким:

Что уже позволило делать такие эффекты:
В заключении
Спасибо за внимание! Существует множество способов делать эффекты вихря, торнадо и прочего в играх. Данный способ будет скорее полезен в ознакомительных целях с функционалом VFX Graph + ознакомлением с некоторыми идеями, которые могут кому-то пригодится. А также показывает, что знание математики бывает весьма полезно в работе разработчика игр. Хотя данный эффект я бы возможно применил не для самого торнадо, а для визуализации его последствий или какой-то «рядом летающей пыли». Это конечно не совсем вихри, так как в реальном вихре кривые будут сходиться к центру и вниз, но как некоторый сильно упрощённый визуальный эффект может быть кому-то полезен.
ссылка на оригинал статьи https://habr.com/ru/post/668332/
Добавить комментарий