Всем привет, меня зовут Григорий Дядиченко, и я обожаю VFX. В данной статье хочется больше поговорить про VFX Graph, про его функции и про то, как там можно сделать простенькие вихри (разными способами). Если вам интересна тема Unity и VFX, добро пожаловать под кат.
![](https://webcf.waybackmachine.org/web/20220528154946/https://habrastorage.org/getpro/habr/upload_files/ce9/37b/a06/ce937ba06559efe54cb91f046277db39.png)
Сразу скажу, что эта статья скорее про работу с VFX Graph, чем про создание самого по себе вихря. С двух точек зрения. Если вам нужно сделать красивое торнадо, есть способы оптимальнее и лучше. Как пример один способ описывается тут и он часто будет оптимальнее, проще и эффектнее. С другой стороны, я не буду разбирать "симуляцию вихря", уравнения Навье-Стокса или циркуляционную теорему Кельвина. Мы будем разбирать, как сделать эффект похожий на вихрь, какие инструменты есть для этого в VFX Graph и т.п. Подобная работа с частицами может скорее дополнить эффект из видео выше, или сделать через частицы воздействие на окружение подобных торнадо. Ну для начала покажем что получилось.
Подготовка графа
В отличии от Shuriken в VFX Graph эммитеры по форме не выравнивают скорость по этой форме. Если мы хотим сделать аля торнадо, первое что нам нужно сделать — это эммитер в виде конуса. Такой в VFX Graph есть.
![](https://webcf.waybackmachine.org/web/20220528154946/https://habrastorage.org/getpro/habr/upload_files/54f/7d8/9dc/54f7d89dc3f9921a8cddcdb502955c15.png)
Также заменив стандартные партиклы на более мягкие и увеличив число частиц получится примерно такой эффект. Для удобства нам так же понадобится контролировать угол нашего вихря и высоту. Можно это конечно делать напрямую через радиусы и параметры конуса, но угол является более понятной метрикой.
Конус в сущности представляет из себя "закрученный" треугольник. Если разобрать треугольник, то в нашем случае он состоит из Top Raduis и Height. При этом из математики известно, что тангенс угла равен отношению противолежащей стороны к прилежащей в прямоугольном треугольнике. Так как задавать нам нужно высоту и угол, то осталось найти Top Radius. На рисунке ниже можно посмотреть расчёт.
![](https://webcf.waybackmachine.org/web/20220528154946/https://habrastorage.org/getpro/habr/upload_files/3e8/3d2/ce1/3e83d2ce1d9566c2a840e6cdc008ede8.png)
То есть радиус равен тангенс угла при основании, умноженный на высоту. Давайте перенесём это всё в VFX Graph.
![](https://webcf.waybackmachine.org/web/20220528154946/https://habrastorage.org/getpro/habr/upload_files/28d/a1e/519/28da1e519c2fb8c37e6ddcfb01d7097d.png)
Так как углы привычнее задавать в градусах, а не в радианах, а в тангенсе угол в радианах, то сначала мы переводим градусы в радианы по формуле:
Но так как мне удобнее использовать общий угол из основания конуса, то мы делим его на 2 или вместо 180 делим на 360. Всё вынесено в графе в внешние параметры для удобства контроля, теперь мы можем регулировать наш конус углом и высотой.
Так же в VFX Graph мы можем контролировать спавн частиц. В целом чтобы при изменении высоты и угла не менялась (до определённого предела) плотность частиц вихря, нам нужно изменять рейт спавна в зависимости от параметров. Так как я хочу, чтобы частицы были на боковой поверхности конуса, логично использовать за некий параметр использовать площадь боковой поверхности конуса. Формула прощади боковой поверхности конуса:
![](https://webcf.waybackmachine.org/web/20220528154946/https://habrastorage.org/getpro/habr/upload_files/713/c19/fdc/713c19fdc18d4eb6daedec8d84ef4441.png)
так что теперь нам надо найти l. Для этого есть несколько способов, как пример теорема Пифагора, но мы воспользуемся более простым, так как у нас есть угол, да ещё и в радианах. Как известно из той же тригонометрии:
в наших терминах. Поэтому искомая:
Запишем это в виде графа с формулой боковой поверхности конуса:
![](https://webcf.waybackmachine.org/web/20220528154946/https://habrastorage.org/getpro/habr/upload_files/fd4/e65/237/fd4e65237c12e30c2237a12635651e62.png)
Итак, со спавном мы вроде разобрались. Да, стоит сказать что математика выше подходит чтобы получить равномерное распределение частиц на поверхности конуса. Для распределения частиц в объёме нужна формула объёма. То, что частицы спавнятся на поверхности задаётся в настройках Set Position (Shape: Arc Cone). И дополнительная константа в графе и параметр Rate нужны просто для удобства.
Путь 1. Касательная к окружности
Пора начать разбираться со скоростями. Первая идея, что мне пришла в голову, чтобы получить нужный эффект. Касательная к окружности конуса. Если посмотреть на конус сверху, то это просто серия вложенных окружностей. Мы всегда можем узнать позицию частицы в VFX Graph с помощью Get Attribute: position, а дальше всё дело техники. Так как у нас локальная система координат, то нужная нам касательная к окружности — это нормаль к радиусу. Нормаль в нашем случае представляет из себя:
Так как мы находимся в плоскости XZ. Но в локальной системе координат мы возьмём ещё за упрощения, что все частицы вращаются вокруг оси (0, 0). Так что dx = x - 0 = x, где x — позиция конкретной частицы. То есть:
Что в графе превратится в
![](https://webcf.waybackmachine.org/web/20220528154946/https://habrastorage.org/getpro/habr/upload_files/b3d/f7a/79d/b3df7a79d4e4e3749038153cc1a0abb4.png)
и выглядит как-то так:
Выглядит в целом неплохо, но у этого способа есть одна проблема. Если мы попробуем добавить скорость вращения частиц, то частицы начнут выходить на новые орбиты чисто из-за принципа решения. Для примера скорость вращения частиц 5:
Если что скорость делается просто домножением вектора скорости на константу.
![](https://webcf.waybackmachine.org/web/20220528154946/https://habrastorage.org/getpro/habr/upload_files/9a6/f12/a3a/9a6f12a3a13bea0ace7bfbee69d64bb9.png)
Путь 2. Вращение частиц
Чтож, так не получилось. Давайте попробуем что-нибудь другое. Тут я пожалуй сразу покажу граф целиком, а потом объясню, что он делает и почему:
![](https://webcf.waybackmachine.org/web/20220528154946/https://habrastorage.org/getpro/habr/upload_files/bcc/9ea/417/bcc9ea417fc6d14d4452aff3ecf67d19.png)
Выглядит этот вихрь уже вот так:
Идея такова, что мы работаем теперь не в скоростях, а в позиция. У нас есть центральная ось и вокруг неё в плоскости XZ мы вращаем частицы. Поэтому важно, что теперь задаётся позиция, а не скорость. Скорость зависит от радиуса окружности, чтобы частицы двигались быстрее, если они находятся на большей орбите + добавлен небольшой рандом для более "натурального" эффекта. Верхняя часть с эммишеном частиц никак не изменилась, по сути мы изменили только принцип движения. Визуально в целом неплохо и можно менять скорость, при этом ни одна частица не уйдёт с орбиты. Но потом я решил добавить ещё одну функцию "наклон орбит" и граф стал таким:
![](https://webcf.waybackmachine.org/web/20220528154946/https://habrastorage.org/getpro/habr/upload_files/780/92d/ecc/78092decc216999fea6e1c960bb8cff9.png)
Что уже позволило делать такие эффекты:
В заключении
Спасибо за внимание! Существует множество способов делать эффекты вихря, торнадо и прочего в играх. Данный способ будет скорее полезен в ознакомительных целях с функционалом VFX Graph + ознакомлением с некоторыми идеями, которые могут кому-то пригодится. А также показывает, что знание математики бывает весьма полезно в работе разработчика игр. Хотя данный эффект я бы возможно применил не для самого торнадо, а для визуализации его последствий или какой-то "рядом летающей пыли". Это конечно не совсем вихри, так как в реальном вихре кривые будут сходиться к центру и вниз, но как некоторый сильно упрощённый визуальный эффект может быть кому-то полезен.