Unity VFX Graph
主な参照サイト
VFX Graphの良いところ・悪いところ
良いところ
・GPUで計算するので、Shurikenに比べてたくさんのエフェクトが発生させることができる
・Property Binderを使用して、オブジェクトの位置情報やキー入力を取得できる。Shurikenの場合はスクリプト作成しないといけない。
悪いところ
・カーブエディタが使いずらい。Shurikenだとカーブエディタで値を入力できるが、VFX Graphだと0-1までしか値を取らないため、Multiplyで乗算する必要がある。
・テクスチャアニメーション(Flipbook Player)が限定である。
LocalスペースとWorldスペースの違い
オブジェクトが移動したときにエフェクトが追従するかしないかの違い。
ブロックのLocalとWorldの違いは、
Spawnコンテキスト
エフェクトの発生量や発生する時間を、間隔を設定できる。
インスペクター
Loop Duration
→パーティクルを生成する秒数を指定できる。
無限と定数とランダムを指定できる。
Loop Count
→ループする回数を指定できる。
無限と定数とランダムを指定できる。
Delay Mode
→遅延の方法と秒数を指定できる。
Initialize Particleコンテキスト
エフェクトの発生時の位置や寿命などの初期表示を指定できる。
エフェクト発生時に一度呼ばれる。
Capacity
パーティクルの最大数を指定できる。
この数が多いとその分メモリ容量が増える。
Bounds Mode
バウンディングボックスの範囲の指定方法を設定できる。
バウンディングボックスがカメラ見えなくなるとエフェクトが発生しなくなる。
Recorded
バウンディングボックスをエフェクトが再生しながら指定できる。
Manual
BoundsにAxis Aligned Boxノードで繋いでバウンディングボックスの範囲を指定できる。
Automatic
毎フレームバウンディングボックスを自動で計算してくれる。
他に比べて負荷がかかる。
また、Boundsを球の形にもできる。
Update Particleコンテキスト
発生したエフェクトに対して位置や色の変化などを毎フレーム更新を行う。(負荷の注意)
Output Particleコンテキスト
最終的なエフェクトの見た目や形状を決定する。
Shader Graph
VFX Shader Graphを指摘できる。
これを指摘すると、BlendModeなどは消え、ShaderGraph上の設定が適用される。
Color Mapping
テクスチャをDefalutかGradient Mappedを指定する。
Defalutは設定したテクスチャのまま。
Gradient Mappedはアルファチャンネルの明るさに応じてGradientで設定した色が反映される。
Defalut
Gradient Mapped
Uv Mode
テクスチャのUVを制御できる。
Flipbook Layout
テクスチャを2DかArray形式かを選択できる。
Use Sort Partcle
ソフトパーティクルを設定できる。
Use Sort Partcleをオフ
Use Sort Partcleをオン
Blend Mode
Use Alpha Clipping
インスペクター
Space
LocalかWorldを指摘できる。
Mesh Count
Output Partcle Meshの場合に表示される。
メッシュの種類を指定できる。
下の例だと、Mesh Countが4で、4つのメッシュが指定できている。
Primitive Type
Triangle、Quad、Quadを指摘でき、その際Output Particleが設定に応じて変わる。
Sort
Sort Mode
Revert Sorting
Compute Culling
Frustom Culling
Cast Shadow
Cull Mode
Z write Mode
Z Test Mode
Sorting Priority
-------ブロック 始まり-------
Attribute
age
alive
Set Alive
パーティクルの生存の有無を設定できる。
Trueならパーティクルは描画され、Falseならパーティクルは描画されない。
下の例では、テクスチャのアルファチャンネルを利用してパーティクルの描画するサーフェイスを制御している。
alpha
Set Alpha
アルファを設定できる。
下の例だとSine Waveで点滅させている。
パーティクルの生存期間の始まりと終わりで点滅させている。
angle
Set Angle
角度を指定できる。
下の例だと、角度をランダムにすることで炎の見た目を同じに見えないようにしている。
下の例は0、90、180,270度で角度を指定したいがSet Angle XYZRandomだけだとばらばらになるので、
Set Angle XYZRandomで3.99にすることでintにキャストしたときに0-3の範囲になることを利用して、
0-270度を表現している。
Perlin Noiseで葉っぱの揺らぎを表現している
角度を変えて花を円を描くようにしている
Get Attribute:PositionとValue Noiseでパーティクルごとにランダムな角度を表現している
angularVelocity
Set Angular Velocity
回転速度を加えることができる。
Set Angular Velocity by Speed
速度によって回転速度を反映させる。
下の例だと、Set Angular Velocity by Speedがオフの場合、当たり判定を検知した後も回転しているが、オンの場合は回転がしていない。
axisX
axisY
Set Axis Y
y軸を起点に、サイズや回転を調整できる。
axisZ
Set Axis Z
Z軸を起点に、サイズや回転を調整できる。
color
Set Color
色を設定できる
下の例だとPerlinNoiseを使用して、ばらばらなランダムではない色に設定している 下の例だとValueNoiseを使用して、ランダムな色を指定している。 下の例だとGetAttribute:PositionとValueNoiseを使用して、パーティクルごとに異なる色をランダムで指定している。 Smoothstepで、パーティクルの寿命に基づいてアニメーション化された色マスクを作成しているSet Color over Life
生存期間に沿って色を反映させる。
Set Color Random from Gradient
Color指定した範囲内の色からランダムに色を取得する
custom
Set Custom Attribute
入力値を設定できる。
設定した値をGet Custom Attributeで取得できる。
Derived
direction
Set Direction
パーティクルの方向を設定できる。
下の例だとPerlin Noiseを使用して、羽を小刻みな動きを実現している。
Add Direction
パーティクルの方向を加算できる
Inherit Source Direction(Set)
親パーティクルの方向を継承する。
lifetime
Set Lifetime
生存期間を設定できる。
下の例では、パーティクルのサイズによって生存期間を設定している。
パーティクルのサイズが大きいほど生存期間が長くなる。
下の例だと、Set SpawnEvent LifeTimeで設定した値を取得して少しずつパーティクルを生成している。
mass
Set Mass
質量を設定できる。
質量が大きいとパーティクルに外力が加わったときの力が大きくなる。
meshIndex
Set Mesh Index
メッシュを指定できる。
oldPosition
pivot
Set Pivot
パーティクルのpivotを変更できる。
下の例では、pivotの位置をy軸にずらして地面にパーティクルが地面にめりこむのを防いでいる。
下の例だとパーティクルの位置を調整している。
下の例だと、xとz軸のPivotをずらしている。
下の例だと、Age Over Lifetimeに沿ってPivotの位置を調整している
position
Add Position
座標を足し算する。
下の例はメッシュにめり込まないように調整している。Add Position(Mesh)
メッシュを指定して、座標角度スケールを調整できる。
Inherit Source Position(Set)
親パーティクルが消失するときの座標を設定する。
Set Position from Map
テクスチャの情報をもとに色々できる。
Set Position
座標を設定できる。
パーティクルの座標がノイズによって不規則になっている。
Get Age Over LifeTimeとSample CurveとLerpを使用してY軸に座標を設定している。
Add Position On Signed Distance Field
scale
Set Scale
スケールの設定ができる。
Set Scaleが1
Set Scaleが0.1
また、Upadateでランダムにスケール変えてパーティクルに変化を与えている。
徐々にビームの大きさを変えている。
Set Scale by Speed
速さの大きさによってパーティクルのScaleを反映させる。
size
Set Size
サイズを設定する。
下の例だとAge Over Lifetimeに沿って、サイズを変更している。
下の例だとPerlinNoiseを使用して、ばらばらなランダムではないサイズ感に設定している
Set Size over Life
Set Size by Speed
Set Size Random from Curve
Set Size Random from Curve(Constant per partcle)
Set Size Custom
上5つは、下の動画分かりやすい。
targetPosition
Set Target Position
Set Target Positionは、Set Positionと一緒に使い、Set Positionが開始点でSet Position Targetが終了点で、開始点から終了点から座標が移動するイメージ。
上の現在のパーティクルと次のパーティクルの関係性は以下である。
状態 | Modulo | Compare | Branch | Divide |
---|---|---|---|---|
現在 | 1 | × | × | 0.01 |
次の | 2 | False | 2 | 0.01 |
現在 | 99 | × | × | 0.99 |
次の | 100 | True | 100 | 1 |
また違うサンプルは以下の動画である。
texIndex
Set Tex Index
連番テクスチャのテクスチャを指定できる。
パーティクルの生存期間に沿って連番アニメーションできる。 Updateコンテキストで、Set Tex Indexを設定して複数のパーティクルにそれを利用している。 また、velocity
Blend Velocity
速度をBlendでブレンドする。
Collision
Collide with AABox
Collide with Cone
円錐状の当たり判定を検知。
Collide with Depth Buffer
パーティクルを特定のカメラの深度バッファと衝突させます。これは特に火花や雨など、精密な衝突はあまり大事ではない、動きの速いパーティクルに便利です。
Collide with Plane
Planeで当たり判定を検知。
Collide with Signed Distance Field
SDFの形状で当たり判定を検知。
Collide with Sphere
球体で当たり判定を検知。
Custom
Increment Strip Index On Start
Set Spawn Time
Spawn Over Distance
前フレームのPositionの変化に応じてパーティクルを発生させる。
Rate per Unit
→パーティクルの量を設定。
Velocity Threshold
→この値よりも早く移動するとパーティクルを発生しなくなる。
公式ドキュメントでは、独自実装もできると書いてある。
このブロックは VFXSpawnerCallback インターフェースを使い、独自の実装作成に参照として利用できます。このブロックの実装は、com.unity.visualeffectgraph > Runtime > CustomSpawners > SpawnOverDistance.cs にあります。
下の例では
Spawn Over DistanceとChange Space(Position)を利用して、ドアの閉開に合わせてパーティクルの発生量を変える
Flipbook
Flipbook Player
Set Tex Indexを使用せずに連番アニメーションができる。
なお、Set LifeTimeなどの値が大きいと、連番アニメーションがループしてしまうためそうしたくない場合はWrapModeをClampにするForce
Conform to Signed Distance Field
SDFを利用して、パーティクルを引き寄せて内部で乱流表現ができる。
Conform to Sphere
球にエフェクトを引き寄せる。
こうすることで、パーティクルエミッタが動いてもパーティクルの発生位置がずれない。
Force
パーティクルの速度を変える。
Gravity
重力を設定できる。
また、Random Numberを使用すると、火花のように飛び散り方の表現ができる。 Age Over Lifetimeに沿ってGravityを有効無効にしている Gravity、Set Velocity Randomを利用して放物線を表現しているLinear Drag
パーティクルの方向に影響を与えずに、パーティクルを減速させる。
Turbulence
乱気流を起こせる。
うねりパターン同じようにしない 理論的に理解するには下記を参考にするといいらしい。Vector Field Force
Houdiniで出力したベクターフィールドを使用できる。
GPU Event
Trigger Event Always
1フレームにイベントを伝える回数をCountで指定する。
Trigger Event On Die
パーティクルが消失するとき、イベントを伝える。
下の例だと、パーティクルの座標とコライダーの座標の距離を比較してTrigger Event On Dieの有無を判定している。Trigger Event Rate
一定間隔でパーティクルにイベントを伝える。
パーティクルの速度が極端に早い場合は、Over Distanceにするとよい。
また、トレイルのかくかくをRateを上げてなめらかにできる。
Rate10
Rate300
参照サイト
HLSL
Custom HLSL Block
Implicit
Integration : Update Position
Integration : Update Rotation
Initialize Particleなどで設定したSet Angular Velocityの値を、毎フレーム加算していく
以下が式である。
angleX += angularVelocityX * deltaTime;
angleY += angularVelocityY * deltaTime;
angleZ += angularVelocityZ * deltaTime;
下の例だと、Age Over Lifetimeに沿ってIntegration : Update Rotationを有効無効にしている
Kill
Kill (AABox)
ボックス内のパーティクルを消す
Kill (Sphere)
Orientation
Connect Target
指定した座標にパーティクルの向きを変え、引き延ばす。
また次の例は、指定したカメラのカラーバッファをConnect Targetを使用して、パーティクルを引き延ばしている。Orient: Face
エフェクトの向きを指定できる。
下記サイトが非常に分かりやすい。
参照サイト
Advanced
Output
Camera Fade
カメラの距離によってパーティクルのアルファフェイドを制御できる。
Subpixel Anti-Aliasing
Subpixel Antialiasingを適用できる。
Subpixel Antialiasingとは、1ピクセルの赤青緑を一つのものとして扱うもの。
イメージ的には下記となる。
公式ドキュメントによると以下ような記載がある。
ブロックがパーティクルを拡大すると、パーティクルのアルファを減少させてパーティクルの寄与とバランスを取ります。
実際に有効無効を比べてみたがそこまで変化がなかった。
無効
有効
Position
Set Position (Depth)
Set Position (Depth)は指定したカメラからのポストエフェクト前のカラーバッファなどを設定できる。
下の例では、この指定したカメラのカラーバッファを元に、Multiply ColorでPerlinNoiseで色を調整しホログラムっぽくしている。
Set Position (Mesh)
静的メッシュ(アニメーションがついていない)にパーティクルを、頂点、エッジ、ポリゴンごとに発生させる。
Set Position (Signed Distance Field)
SDFに沿って、パーティクルを発生させる。
Set Position (Skinned Mesh)
ボーンアニメーションするメッシュの頂点・サーフェイス・エッジにパーティクルを配置させる。
Set Position (Sequential:Three Dimensional)
xyz軸上にパーティクルを設定できる
Set Position (Sequential:Circle )
Set Position (Sequential:Line)
Set Position (Shape : AABox)
Set Position (Shape : Circle)
Shapeが円上にできる。
Set Position (Shape : AicCircle)
Shapeが円上にできる。
Set Position (Shape : Cone)
Set Position (Shape : Line)
Shapeが線上にできる。
Set Position (Shape : Sphere)
ノード上はArc Sphereと表示されているが、公式ドキュメントだとSphereになっている。
形状がShapeの座標を設定できる。
また、プロパティでArc Sphereでサイズを調整できる。
球の周りをぐるぐる動く表現もできる
Tile/Warp Positions
Set Position On Static Mesh
指定したメッシュ上にパーティクルを設定する
三角形の指定した位置にパーティクルを設定しているSize
Screen Space Size
各パーティクルの scaleXYZ プロパティを計算し、ピクセルサイズまたはスクリーンサイズに相対的なサイズにします。
Spawn
Constant Spawn Rate
一秒間のエフェクトの発生量を指定でき、繰り返す。
徐々にパーティクルの発生量を少なくしている。
Single/Periodic Burst
Count
→パーティクルの発生量を指定でき、繰り返さない。
Delay
→パーティクルが発生する遅延時間を指定できる。
Spawn Mode
→パーティクルの数の設定方法を指定できる。
定数かランダムを指定できる。
Delay Mode
→パーティクルが発生する遅延時間の方法を指定できる。
定数かランダムを指定できる。
Repeat
→パーティクルをループするかの設定。
Singelはループしない。
Periodicはループする。
Variable Spawn Rate
Rateで指定した2つの値を発生の最小値、最大値として使用し、Periodによって指定された期間で発生量がリニア補間される。
正直使いづらいし、分かりずらい。
参照サイトのp158
Set SpawnEvent
Set SpawnEvent Color
色を変更できる
下の例だと、RandomNumberで0-1でSampleGradientで色をランダムに設定している。
なお、今回の例では、Initialize ParticleでInherit Source Color(Set)を設定しないと色は反映されない。
Set SpawnEvent Lifetime
生存期間を設定できる。
Velocity
Velocity from Direction & Speed (Change Speed)
Shapeの形状に沿ってパーティクルが進む。
Velocity from Direction & Speed (New Direction)
Velocity from Direction & Speed (Random Direction)
Velocity from Direction & Speed (Spherical)
Velocity from Direction & Speed (Tangent)
-------ブロック 終わり-------
-------ノード 始まり-------
Context
Event
GPUEvent
Initialize Particle
Output Mesh
Output Distortion
歪むの表現ができる。
ただ対応しているのHDRPのみ。
参照サイト
Output Particle Forward Decal
Output Particle Line
線のパーティクルを出力できる。
Output Particle Mesh
Output Particle URP Lit Decal
デカールを出力できる。
Output Particle Point
Output Particle Primitive
Output Particle Octagon
八角形プリミティブのパーティクルを出力できる。
余分なジオメトリをプッシュする代わりにオーバードローを減らすのに役立つ八角形プリミティブは、パーティクル テクスチャに厳密に適合し、不要な透明領域のレンダリングを回避するのに役立ちます。
Output Particle Quad
Output Particle Triangle
Output ShaderGraph Quad
Output ShaderGraph Mesh
Output ShaderGraph Strip
Operator
Attribute
■Age Over Lifetime
パーティクルの生存期間を0-1に返す。
パーティクルの初めは0に近く、パーティクルが消えるころには1になる。
下の例だとパーティクルが消えるころにつれて、乱気流の強さが強くなっている。
また、パーティクルの生存期間に沿って連番アニメーションできる。
■Get Attribute: age
パーティクルの発生からの経過時間を取得する。
■Get Attribute: alive
■Get Attribute: alpha
■Get Attribute: angle
現在の角度を取得する。
今回は0、90、180,270度で角度を指定したいがSet Angle XYZRandomだけだとばらばらになるので、
Set Angle XYZRandomで3.99にすることでintにキャストしたときに0-3の範囲になることを利用して、
0-270度を表現している。
■Get Attribute: angularVelocity
■Get Attribute: axisX
■Get Attribute: axisY
■Get Attribute: axisZ
■Get Attribute: color
■Get Attribute: direction
方向を取得する。
以下の例では、調整前はY軸方向にしかパーティクルが進んでいないが
調整後は、Shapeの方向にパーティクルが進んでいる。
なお、Velocity from Direction & Speed (Change Speed)などを使用すれば一々このような処理を加えな良くてもShapeの方向にパーティクルが進んでいく。
■Get Attribute: lifetime
■Get Attribute: mass
■Get Attribute: oldPosition
■Get Attribute: particleCountInStrip
Particle Per Strip Countで指定した値の実際にパーティクルとして描画されている数。
■Get Attribute: particleID
パーティクル一つ一つにIDが割り振られており、それを符号なし整数型で取得できる。
下の例でいうと、particleIDを割った余りによって、いろいろを処理を分けている。
また、下の例は、キャラの両手にパーティクルのエミッタを設定している。
■Get Attribute: particleIndexInStrip
Particle Per Strip Countで指定したパーティクルのインデックス。
0から始まる。
■Get Attribute: stripIndex
Strip Indexで指定した値。
■Get Attribute: pivot
■Get Attribute: position
■Get Attribute: scale
■Get Attribute: seed
■Get Attribute: size
■Get Attribute: spawnIndex
パーティクルが生成された際のインデックスを取得できる。
■Get Attribute: spawnTime
■Get Attribute: targetPosition
■Get Attribute: texIndex
■Get Attribute: velocity
■Get Custom Attribute
Set Custom Attributeで設定した値を取得できる。
Bitwise
■And
■Complement
■Left Shift
■Or
■Right Shift
■Xor
BuiltIn
■Delta Time
現在と前のフレーム間の時間 (秒) を出力できる。
これによって、FPSが変動しても同じ動きする。
■Frame Index
■Local To World
■Main Camera
カメラの情報を取得できる
以下の動画だとカメラの座標とエフェクトの距離を算出して、カメラがエフェクトから遠くなるとパーティクルが消えるようにしている。
■System Seed
■Total Time
パーティクルの発生してからの経過時間。
■World To Local
Camera
■Viewport To World Point
■World To Viewport Point
Color
■Color Luma
Color Lumaによって頂点カラーの輝度でカラーを制御している。
これを使用すると、パーティクルの色を変更しながら、元の明るさを維持することができます。
これをシミュレーション自体に活用して、最も明るい粒子をより速く移動させることができます。
■HSV to RGB
■RGB to HSV
HLSL
■Custom HLSL
Inline
■AABox
■AnimationCurve
■ArcCircle
■ArcCone
■ArcSphere
■ArcTorus
■bool
■Camera
■CirclePolo
■Color
■Cone
■Cubemap
■CubemapArray
■Cylinder
■Direction
■FlipBook
パーティクルの生存期間に沿って連番アニメーションなどができる。
■float
■Gradient
■int
■Line
■Matrix4x4
■Mesh
■OrientedBox
■Plane
■Position
■Sphere
■TerrainType
■Texture2D
■Texture2DArray
■Texture3D
■Torus
■Transform
■uint
■Vector
■Vector2
■Vector3
■Vector4
Logic
■And
■Branch
■Compare
Conditionを条件にして、TrueかFalseを返す。
下の動画だと、
3秒までTurbulenceとForceが有効で
2.5秒過ぎたらGravityとCollide With Plameが有効になる。
■Nand
■Nor
■Not
■Or
■Probability Sampling
確率サンプリングを使用してランダムを表現できる。
確率サンプリングを使用すると、値の均一性が低下し、サイズの変化、色の分布などについてより興味深い結果が得られます。
ランダムで表現できるRandomNumberと比較してみたが確かに、確率サンプリングの方が値が均一化していないような印象受ける。
■Switch
Switch構文を使用できる。
Random Numberは0-2.99をランダムで出力するが、Switch構文に入力値として整数でにキャストされる。
例えば0.9ならValueは0になるので、Vector3(1,0,0)が出力される・
Math
■Absolute
■Add
■Divide
■Fractional
■Inverse Lerp
■Lerp
Lerpで補間する。
■Modulo
■Multiply
■Negate
■One Minus
■Power
■Reciprocal
■Sign
■Smoothstep
■Square Root
■Step
■Subtract
■Ceiling
■Clamp
■Discretize
■Floor
■Maximum
■Minimum
■Round
■Saturate
■Epsilon
■Pi
Pi (π) を返します。
ラジアン→度数
2πは360度になっている。
度数→ラジアン
360度から2πになっている。
■Polar to Rectangular
極座標から直交 XY 空間変換する。
XY 座標を取得できる。
下の例だと、まとまったコインのかたまりをまばらにしている。
■Rectangular to Polar
直交 XY 空間変換から極座標にする。
出力角度(ラジアン単位)と原点までの距離を取得できる。
参照サイト
■Rectangular to Spherical
■Spherical to Rectangular
■Exp
■Area (Circle)
■Change Space
ローカル(ワールド)座標がどれだけ移動したか取得できる。
下の例だと、ドアの煙がドアの移動量によって煙の量が多くなっている。
下の例だとパーティクルの位置をワールド空間に変え、ワールドの位置によってパーティクルが重力で落ちるようにしている。
■Distance (Line)
■Distance (Plane)
ある座標からのPlaneまでの、一番近い距離と一番近い座標を取得できる。
下の例では、
SampleMeshの座標とDistance Planeの距離を求めて、距離が近いほど早く消滅させている
■Distance (Sphere)
■InvertTRS (Matrix)
■Transform (Direction)
Directionを調整できる。
■Transform (Matrix)
■Transform (Position)
Transform(Position、Angel、Scale)にPostionを反映させる。
■Transform (Vector)
■Transform (Vector4)
■Transpose (Matrix)
■Volume (Axis Aligned Box)
■Volume (Cone)
■Volume (Cylinder)
■Volume (Oriented Box)
■Volume (Sphere)
■Volume (Torus)
■Log
■Remap
Remapを使用できる。
■Remap [0..1] => [-1..1]
■Remap [-1..1] => [0..1]
■Acos
■Asin
■Atan
■Atan2
Atan2を返す。
以下の動画だと、パーティクルの進行方向に合わせてMeshの角度を調整している。
何故このような実装になるのかは、参照サイトのp190
また、対象物に方向を向かせることなどもできる。
VFX Property Binderを使用して可能
■Cosine
CosΘを返す。
下の例では、円状の点Pの座標を(CosΘ,SinΘ)で表している。
参照サイトのp177
■Sine
SinΘを返す。
下の例では、円状の点Pの座標を(CosΘ,SinΘ)で表している。
参照サイトのp177
■Tangent
■Append Vector
■Construct Matrix
■Cross Product
■Distance
距離を求める。
■Dot Product
■Length
ベクトルの大きさを取得できる。
下の例だと、現在の速度(向きと大きさ)から速さ(大きさ)を取得している。
利用できる型は、Inputは以下。
Position
Vector
Vector3
Vector2
float
■Look At
■Normalize
ベクトルを正規化できる。
下の例だと、現在の速度を正規化している。
利用できる型は、Inputは以下。
Position
Vector
Direction
Vector3
Vector4
Vector2
float
■Rotate 2D
■Rotate 3D
指定した中心の周りで、指定した角度で、 回転させる。
参照サイトのp192-p193
なので、これを解消するため、Set Velocity from Direction & Speed (New Direction)や外積を利用していく。
参照サイトのp194-p197
Get Attribute: directionで行うと、Set Velocity from Direction & Speed (New Direction)では、 directionを上書きするため変な挙動になる
違う一例
■Sample Bezier
ベジェ曲線を作成できる。
■Squared Distance
■Squared Length
■Swizzle
■Sawtooth Wave
■Sine Wave
Sin波を設定できる。
■Square Wave
■Triangle Wave
■Sequential 3D
パーティクルをグリッド上に並べる。
■Sequential Circle
■Sequential Line
Noise
■Cellular Curl Noise
■Cellular Noise
■Perlin Curl Noise
Perlin Curl NoiseはPerlin Noiseをベースに乱気流のようなノイズを追加したもの。
パーティクルの座標がノイズによって不規則になっている。
■Perlin Noise
Perlin Noiseを取得できる。
■Value Curl Noise
■Value Noise
Value Noiseを取得できる。
OctavesとDimensionsは値が低い方が負荷がかからない。
Random
■Random Number
最大値と最小値を指定して、ランダム値を設定できる。参照サイト
上の動画だとシンプルな紹介なので、もう少し踏み込んで紹介する。 ほとんどの場合は、Per Particleでいいが、下記動画のようなパーティクルまとまった表現をしたい場合はPer Componentを使用するのが良い。Sampling
■Buffer Count
「GraphicsBufferを使用してオブジェクト同士の間で帯電エフェクトなどを作成する」の「1.」を参照。
■Get Mesh Index Count
■Get Mesh Triangle Count
Meshのポリゴン数を取得できる。
■Get Mesh Vertex Count
■Get Skinned Mesh Index Count
■Get Skinned Mesh Triangle Count
■Get Skinned Mesh Vertex Count
■Get Skinned Mesh Local Root Transform
■Get Skinned Mesh World Root Transform
■Get Texture Dimensions
■Load CameraBuffer
■Load Texture2D
■Load Texture2DArray
■Load Texture3D
■Position (Depth)
カメラの深度から、ワールド空間の座標を求める。
下の例では、パーティクルの座標をビューポート空間に変換し、それをPosition (Depth)に設定しxy座標のワールド空間を求めている。
■Sample Buffer
「GraphicsBufferを使用してオブジェクト同士の間で帯電エフェクトなどを作成する」の「1.」を参照。
■Sample CameraBuffer
■Sample Curve
Timeの値に沿って、値が変化する。
■Sample Gradient
Gradientの色を設定できる。
RandomNumberで0-1でSampleGradientで色をランダムに設定している。
■Sample Mesh
設定したモデルの頂点の情報(座標、頂点カラー、UV、法線など)を取得できる
■Sample Mesh Index
■Sample Skinned Mesh
ボーンアニメーションしているモデルの、頂点、エッジ、ポリゴンからパーティクルを発生させる。
■Sample Skinned Mesh Renderer Index
■Sample Signed Distance Field
SDFテクスチャを指定できる。
SDFは、モデルからどのくらい離れているか表したをテクスチャのこと。
これを利用するとモデルにパーティクルが這ったり、遠ざかったり、近づいたりなどの表現が可能。
■Sample Texture2D
■Sample Texture2DArray
■Sample Texture3D
3Dテクスチャを使用できる。
下の例ではHoudiniから出力したベクターフィールドを使用している。
■Sample TextureCube
■Sample TextureCubeArray
Spawn
■Spawn State
Spawnコンテキストの値を取得できる。
Time
■Periodic Total Time
Rangeで指定した範囲を、Periodの秒数で出力する。
■Total Time(Per-Partcle)
Utility
■Point Cache
Point Cacheを設定できる。
Point Cacheの形状にパーティクルを発生させたりできる。
System
Empty Particle System
Simple Heads And Sparks
Simple Heads And Trails
トレイル表現を作成できるノード
参照サイトのp128
Strip Capacity
ストリップの数
Strip Capacityが2の場合
Perticle Per Strip Count
1ストリップの最大パーティクル
Perticle Per Strip Count
Simple Mesh Output
Simple Particle System
Simple Ribbon
Simple Swarm Particle System
Misc
Group Node
-------ノード 終わり-------
Visual Effect Asset
Fixed Delta Time
Project Settings > VFXのFixed Time Stepを使用するか設定できる。
Culling Flags
Boundsとカメラの境界の計算方法を指定できる
Exact Fixed Time
Fixed Delta Time有効時に有効になる。
1フレーム生成する時間が、Fixed Time Stepよりも長い場合、Fixed Time Stepを複数回か呼ぶかを設定できる。
たとえば、フレームに 10 ミリ秒かかり、Fixed Time Stepが 5 ミリ秒の場合、効果は 10 ミリ秒の deltaTime で 1 回更新されるのではなく、5 ミリ秒の deltaTime で 2 回更新されます。これはリソースを大量に消費する操作なので、ハイエンドのシナリオでのみ使用してください。
Ignore Time Scale
Project Settings > TimeのTime Scaleを考慮するか設定できる。
有効にすると、考慮しない。
無効にすると、考慮する。
PreWarm Total Time
Unity がエフェクトをシミュレートする期間を秒単位で設定できる。
正直よくわからない。
PreWarm Step Count
Unity が PreWarm を計算するために使用するシミュレーション ステップの数を設定します。
正直よくわからない。
PreWarm Delta Time
Unity が PreWarm に使用するデルタ時間を秒単位で設定します。
正直よくわからない。
Instancing mode
インスタンス化の設定をできる。
複数のエフェクトが同じVisual Effect Graph アセットを持っている場合、インスタンス化を使用してそれらのエフェクトをバッチ処理できます。これにより、パフォーマンスが大幅に向上します。
設定は三つある。
無効にするか、
エフェクトの内容とビルド プラットフォームに基づいて、バッチ容量を自動的に設定するか、
バッチ容量を指定するか、
(これは、同時に存在するエフェクトの数を適切に見積もっている場合、またはメモリの使用量をより適切に制御したい場合に便利です。
カスタム容量を設定すると、効果はすべてのプラットフォームで同じ値を使用します。パフォーマンスの低下が起こらないようにするには、さまざまなシナリオでプロファイリングする必要があります。)
がある。
参照サイト
Initial Event Name
Event Nameの初期値を設定できるようだが、変更しても反映されなかった。
Output Render Order
VFXGraph内に複数のパーティクルがあった場合、描画順を変更できる。
Shaders
UnityがVisual Effect Graph用にコンパイルしたすべてのシェーダーのリストを定義します。
何のためにあるのかよくわからない。
VFXGraphのサンプルが入っているプロジェクト
パーティクルを徐々に消す
ShaderGraphを使用している場合、Set Color over LifeTimeでアルファ制御しても生存期間に沿ってパーティクルが消えない。
なので、シェーダ側のAlphaをAge Over LifeTimeとSample Curveを使用して徐々にアルファを小さくしてパーティクルを消す必要がある。
次は、追加でパーティクルがある一定の距離になるとパーティクル消えるよう機能を追加する。
Random Numberで座標を加算してパーティクルの塊をなくす
下の例だと、AddとRandom Numberがないとパーティクルが固まっている。
だがAddとRandom Numberを加えることでそれが解消されている。
ShaderGraphで実装した頂点アニメーションを制御する
マスクテクスチャでパーティクルの色と描画有無を制御する
パーティクルの位置は-1~1の範囲である。
UVは0~1の範囲なので、Remapする。
SampleMeshの座標とDiVector Filedstance Planeの距離を求めて、距離が近いほど早く消滅させる
当たり判定検知した座標から少しずらしてUI表示
ScreenShipDemoを見ていく
カメラから離れるほどアウトラインを太くする
頂点の法線を押し出すことでアウトライン作成する。
その際、カメラから離れているパーティクルほどアウトライン太くする。
ドアの閉開に合わせてパーティクルの発生量を変える
Spawn Over DistanceとChange Space(Position)を利用して、ドアの閉開に合わせてパーティクルの発生量を変える
ホログラムテキスト
ホログラムUI
アルファをばらばらのテクスチャを作成し、Color/Alpha over LifeとSet Lifetime Randomでばらばら感を演出するのがみそ。
プロジェクター
枠のUIを動かす
UIの背景とアウトライン
グリッジUI
プロジェクター
Set PositionとSet Target PositionとConnect Targetがみそ。
ゲージUI
グリッジテキスト
点滅遷移エフェクト
旋回する炎エフェクト
粒子エフェクト
雷エフェクト
ポイントは、Sample Bezierの入力値にCross Productをしたのを入力することである。
歪みエフェクト
Distortion Blur Mapを使用して歪みエフェクトを演出している。
なお、HDRPのみ対応。
Motion Vector Mapによる炎
雷っぽくするコツ
下の例を見ると
・色をHDRにする
・AngleをRandomにする
・サイズを生存期間にそってランダムのサイズにする
煙っぽくするコツ
下の例を見ると
・Set Tex IndexをRandomにする
・Set AngelをRandomにする
・Set AlphaをRandomにする
・Set SizeをRandomにする
・ベースマップのテクスチャを作成する際は、濃淡をつける
・ライティングをうまく適用させたいならNormalMapを作成する
上の例以外だと下の例を見ると
・Set VelocityをRandomにする
・風で動いているようにみせる場合は、PerlinNoiseを使用して、ForceとAdd Velocityを設定する
・ShaderのFlipbookはBlend対応できていないので、自作でBlend対応しているFlipbookを使用する
・Age Over Lifetimeに沿ってSample Curveを設定しShaderGraphのプロパティを以下の項目制御
1.Flowmapでディストーションさせ歪みを徐々に上げていく
2.アルファのしきい値を上げて徐々に透明にしていく
3.二値化を徐々に緩めていく
上の例以外だと下の例を見ると
・Multiply Size over Lifeを使用する。
・ベジェ曲線の煙を作成したいときは、Sample Bezierを使用する。
上の例以外だと下の例を見ると
・Six Way Smokeで動的にライティングを適用させている。
・Probablity Samplingを使用してSet Sizeをランダムにしている
・煙を簡単にグレースケールにする際は、Random Numberに少数点にすれば簡単にできる。
・輪っか上に煙を回転させるには、Arc CircleとBlend Velocity from Direction & Speed(New Dorection)とCross Prodouctを使用する
Trailエフェクト作成するコツ
・ランダムな旋回加えるため、Rotate3DにRandomNumberとProbablityでランダム性持たせる。
・親パーティクルは、Multiply Size over Lifeで徐々に小さくしていく
・子パーティクルは、Multiply Size over Lifeで徐々に大きくしていく
・Color/Alpha over LifeでHDRを使用し、はじめは明るく・不透明、徐々に暗くしていく・透明にしていく
火の粉作成するコツ
・Set LifeTime Randomを使用する
・Set Size Randomを使用する
・Turbulenceを使用する
・Linear Dragで動きすぎるの防ぐ
・Orient Along Velocityを使用する。
・Collider With Depth Bufferを使用する。
・Multiply Color over Lifeではじめは明るく・不透明、徐々に暗く・透明にしていく
・Multiply Size over Lifeで徐々に小さくしていく
以下の火の粉の、色とテクスチャ
地割れエフェクト
輪っかのうねうねエフェクト
わっかのうねうねは、
Set Position (Sequential : Circle)のRadiusとCenterのY軸を調整することで作成している。
DiscretizeとCompareを使用して、値が一致していた場合に指定した色で加算している。
Unity付属のVector FiledをAdd Position from MapとAdd Trarget Position from Mapに設定し歪みを表現している。
うねうねエフェクト
Arc PositionのPositionとRadiusを時間経過ともに変えている。
Perlin Curl Noiseを使用してForceでランダムな動きを加える。ボクセル地形
ハイトマップを利用してスケールを変更。
また、スケールの値によって適用する色を変更している。
ベクターフィールドとポイントキャッシュを使用した例
1.ベクターフィールドとポイントキャッシュを使用
TerainのポイントキャッシュをSet Position from Mapに設定し、Terainのメッシュの位置情報をパーティクルに持たせている。
また、Unityがデフォルトで用意されているベクターフィールドをVector Field Forceでベクトルを算出し、それをパーティクルの速度として利用している。
2.ベクターフィールドを使用
3.ベクターフィールドを使用
先にSet Target Positionについて触れる。
Set Target Positionは、Set Positionと一緒に使い、Set Positionが開始点でSet Position Targetが終了点で、開始点から終了点から座標が移動するイメージ。
上の現在のパーティクルと次のパーティクルの関係性は以下である。
状態 | Modulo | Compare | Branch | Divide |
---|---|---|---|---|
現在 | 1 | × | × | 0.01 |
次の | 2 | False | 2 | 0.01 |
現在 | 99 | × | × | 0.99 |
次の | 100 | True | 100 | 1 |
上の例と同じくポイントキャッシュを使用した例。
Color Lumaによって頂点カラーの輝度でカラーを制御しているのがポイント。
VAT、デカールなどを利用した流体エフェクト
VATを使用して流体アニメーションを作成している。
VATを読み込むカスタムシェーダーを作成し、VATの位置をそのシェーダに渡して頂点アニメーションさせている。
こちらの部分は、参照サイトのように、VATの縦の位置を求めてそれをFlipbook Playerで横に連番アニメーションさせることでVATにベイクした頂点アニメーションのデータを取得している
以下が簡素的なDecalである
デカールのワールド座標に高さによってデカールが落ちていく実装や、デカールが地面に落ちた時の見た目のアーティファクトを改善している。
こちらのアーティファクトの改善として、まずパーティクルの位置をビューポート空間に変換し、それをビューポートのxとy軸にオフセットし、これらを引き算してベクトルを求めてそのベクトル同士を外積することでそのパーティクルの法線を求めている。
この法線を反転させ、Set Aixsに設定し、それをOrient AdvancedのZYに設定することでアーティファクトを防いでいる。(詳しくはこちら)
SDFを使用した例
1.SDFでメッシュの周りを這うようなエフェクトを作成する
Add Position On Signed Distance FieldでSDFの位置をランダムにしている。
Conform to Signed Distance FieldでSDFの周りに吸い寄せるようにしている。
Set DirectionにパーティクルからSDFのベクトルを設定することで、子パーティクルがSDF上に這うような動きに補正している。
2.SDFでメッシュ内部で乱気流が起きているエフェクトを作成
下の例のポイントは以下である。
・Set Positionは、Get Attribute PositionのSourceを利用することで親パーティクルの消えた場所から子パーティクルが発生する。
・Conform to Signed Distance FiledのCenterに、パーティクルの位置を設定している、その際、Sine Waveで動かしている。
・Conform to Signed Distance FiledのAttraction Speedを、パーティクルを引き付ける速度をランダムにする。
・Conform to Signed Distance FiledのAttraction Forceを、パーティクルとパーティクル全体の中心までの距離によって吸引の力を変えている。
・TurbulenceのIntensityを、パーティクルとパーティクル全体の中心までの距離によって強さを変えている。
・TurbulenceのDragを、パーティクルとパーティクル全体の中心までの距離によって抗力を変えている。
・Set Alpha Customで、パーティクルとパーティクル全体の中心までの距離によってアルファを変えている。
・Multiply Colorを、速度に応じて変えている。
3.SDFでメッシュ内部の泡エフェクトを作成
ディゾルブエフェクト
まずはShaderGraphでディゾルブエフェクトの本体の動画を挙げる。
ディゾルブを適用したい箇所をアルファマップを利用してアルファクリッピングを行う、
その際、アルベドとエミッションを合わせるとかっこいい見た目になる。
下の動画で実際にディゾルブエフェクトとVXFGraphを組み合わせている。
ポイントは、カスタムアトリビュートで、Scaleを反転させて本のページを右開き左開きで分けている。
下の動画もディゾルブエフェクトである。
Portalエフェクト
下の動画は色が回転する動画である。
まずArc Torusの中心からパーティクルまでのベクトルを求める。
そのベクトルをもとにRectangular to Polarでラジアンを求める。
そのラジアンに時間経過とともに加算し、2π周期でSampleCurveの値を元にSet Colorで色を制御する。
Rotate3Dで回転した際のベクトルを求めて、それをSet Velocityに設定している。
GraphicsBufferを使用してオブジェクト同士の間で帯電エフェクトなどを作成する
オブジェクト同士を繋げる
以下のスクリプトを簡単に説明すると、マウスでクリックした位置に球体のオブジェクトを生成し、そのオブジェクトの座標をGraphicsBufferを使用して、毎フレームVFXGraphのプロパティに送りその送られた座標をもとにオブジェクト同士の間で帯電エフェクトを作成している。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.VFX;
[ExecuteAlways]
public class BuiltInTypestest : MonoBehaviour
{
[Header("Buffer Data")]
public float radius = 5f;
public float enemyLife = 15f;
public string positionBufferName = "Enemies";
public string healthBufferName = "Health";
[Header("Enemies")]
public GameObject enemyPrefab;
public List<Collider> targets = new List<Collider>();
public List<Vector3> positions = new List<Vector3>();
public List<float> health = new List<float>();
private VisualEffect m_vfx;
private GraphicsBuffer m_positionBuffer;
private GraphicsBuffer m_healthBuffer;
private SphereCollider m_collider;
private int bufferSize = 0;
private float timer = 0f;
// Start is called before the first frame update
void Start()
{
m_vfx = GetComponent<VisualEffect>();
m_collider = GetComponent<SphereCollider>();
SetEmptyBuffer();
}
struct myStruct
{
public Vector3 something;
public float somethinelse;
}
//GraphicsBuffer初期化処理
void SetEmptyBuffer()
{
/* m_positionBuffer = new GraphicsBuffer(GraphicsBuffer.Target.Structured, 1, 12);
m_healthBuffer = new GraphicsBuffer(GraphicsBuffer.Target.Structured, 1, 4);
Vector3[] startPos = new Vector3[1];
startPos[0] = new Vector3(0f, -3f, 0f);
float[] startHealth = new float[1];
startHealth[0] = 1f;
m_positionBuffer.SetData(startPos);
m_healthBuffer.SetData(startHealth);
*/
m_positionBuffer = null;
m_healthBuffer = null;
if (m_vfx.HasGraphicsBuffer(positionBufferName))
m_vfx.SetGraphicsBuffer(positionBufferName, m_positionBuffer);
if (m_vfx.HasGraphicsBuffer(healthBufferName))
m_vfx.SetGraphicsBuffer(healthBufferName, m_healthBuffer);
}
// Update is called once per frame
void Update()
{
m_collider.radius = radius;
if (m_vfx.HasFloat("Radius"))
//VXFGraphのRadiusプロパティに設定
m_vfx.SetFloat("Radius", radius);
if (bufferSize != targets.Count)
{
bufferSize = targets.Count;
Reallocate(bufferSize);
}
for (int i = 0; i < targets.Count; i++)
{
positions[i] = targets[i].transform.position;
}
//マウスクリックした場合
if (Input.GetMouseButton(0))
{
//Debug.Log("Mouse Down");
RaycastHit hit;
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
//カメラからレイを飛ばし当たり判定を検知した場合
if (Physics.Raycast(ray, out hit))
{
timer += Time.deltaTime;
if (timer > 0.1f || Input.GetKey(KeyCode.LeftShift))
{
timer = 0f;
//オブジェクト生成
Instantiate(enemyPrefab, hit.point + Vector3.up * 5, Quaternion.identity);
}
}
}
if (positions.Count > 0)
{
//VXFGraphのEnemiesプロパティに生成したオブジェクトの座標を設定
m_positionBuffer.SetData(positions);
//VXFGraphのEnemyHealthプロパティに生成したオブジェクトの体力を設定
m_healthBuffer.SetData(health);
}
DamageEnemies();
}
//時間経過による体力減少処理
void DamageEnemies()
{
// Damage enemies in range
for (int i = 0; i < health.Count; i++)
{
health[i] -= Time.deltaTime;
if (health[i] <= 0f)
{
GameObject tempRef = targets[i].gameObject;
targets.RemoveAt(i);
positions.RemoveAt(i);
health.RemoveAt(i);
Destroy(tempRef);
}
}
}
void Reallocate(int newSize)
{
if (newSize == 0)
{
SetEmptyBuffer();
return;
}
if (m_positionBuffer != null)
m_positionBuffer.Release();
if (positions.Count > 0)
{
m_positionBuffer = new GraphicsBuffer(GraphicsBuffer.Target.Structured, newSize, 12);
m_healthBuffer = new GraphicsBuffer(GraphicsBuffer.Target.Structured, newSize, 4);
if (m_vfx.HasGraphicsBuffer(positionBufferName))
m_vfx.SetGraphicsBuffer(positionBufferName, m_positionBuffer);
if (m_vfx.HasGraphicsBuffer(healthBufferName))
m_vfx.SetGraphicsBuffer(healthBufferName, m_healthBuffer);
}
m_positionBuffer.SetData(positions);
}
//VFXオブジェクトの当たり判定の初めを検知した時
private void OnTriggerEnter(Collider other)
{
// if ((layer.value & (1 << other.gameObject.layer))! > 0)
// return;
if (!other.CompareTag("Enemy"))
return;
//生成したオブジェクトの座標や体力を設定する
if (!targets.Contains(other))
{
targets.Add(other);
positions.Add(other.transform.position);
health.Add(other.GetComponent<Enemy>().health);
}
}
//TinyTowerオブジェクトの当たり判定の終わりを検知した時
private void OnTriggerExit(Collider other)
{
// if ((layer.value & (1 << other.gameObject.layer))! > 0)
// return;
if (!other.CompareTag("Enemy"))
return;
//生成したオブジェクトの座標や体力をクリアする
for (int i = 0; i < targets.Count; i++)
{
if (targets[i] == other)
{
targets.RemoveAt(i);
positions.RemoveAt(i);
health.RemoveAt(i);
break;
}
}
}
}
Sample Graphics BufferのBufferにプロパティのGraphics Buffer指定し、indexにインデックスを指定すると上の例でいう毎フレームオブジェクトの座標が送られてくる。
stripIndexは0で、Sample Graphics BufferのIndexは0になり現在Graphics Bufferには一つのオブジェクトしか設定していないため(Graphics Buffer Countは0)そのオブジェクトの座標が毎フレーム取得できる。
動きを帯電っぽくする
ベクターフィールドを使用して帯電っぽい動きを加えている。
またGet Attribute: particleIndexInStripとGet Attribute: stripIndexを利用してパーティクルの色を変えている。
Quadでメッシュで描画しているようなカラーテクスチャとノーマルマップ
目盛りエフェクト
一つのカスタムアトリビュートで、違う回転にする。
座標によって色を変える
ランダムに渦を描くように旋回させる
ホログラム
サンプル1
Set Position (Depth)は指定したカメラからのポストエフェクト前のカラーバッファなどを設定できる。
下の例では、この指定したカメラのカラーバッファを元に、Multiply ColorでPerlinNoiseで色を調整しホログラムっぽくしている。
また次の例は、指定したカメラのカラーバッファをConnect Targetを使用して、パーティクルを引き延ばしている。
サンプル2
ハイトマップを利用してパーティクルに凹凸を加えている。
ハイトマップのUVの処理は何故こういう実装になっているのかわからないが、とりあえずハイトマップを使用する際はこの処理を加えるのが良さそう。
上のハイトマップによって配置したパーティクルに対して、波を加えている。
パーティクルの下の座標は黒く、上は白く制御している。
targetPositionは初期値のポインチキャッシュの座標で、positionはUpadate更新されたものになる。
Six Way Smokeでパーティクルを動的ライティングを適用させる
バージョン 16ではURPも対応している。
テクスチャの作り方はこちらを参照。レイトレーシング
バージョン 15.0 以降のHDRPの以下ののレイトレーシング機能が利用できる。
・レイトレーシングによる反射
・屈折、影
・アンビエントオクルージョン
・グローバルイルミネーション
参照サイト
TAAによる違い
TAAを有効にするとパーティクルのぼやきを軽減できる。
なお、HDRPしか対応していない。
Volumetric Fogを適用させる
なおHDRPのみ対応
Fogがあるときの見た目の違い
なおHDRP
Bloomによる色の違い
Houdiniでフローマップを作成するVFXGraphで利用(ベクターフィールドやポイントキャッシュも作成)
Value Noiseで色を設定した際にHDRの色が反映されない時の解消法
ValueNoiseでサイズが大きくなりすぎる場合の解消法
複数の似たようなテクスチャを用意し複数のOutputで、サイズや座標変えて重なり文字を作成する
文字の間隔をSampleCurveで調整する
一つ一つの文字のサイズと色をアニメーションさせる
ライトが点滅しているような表現
頂点カラーにAOの情報を描きこみ、SampleMeshでそのAOの情報取得し、溝の部分の色を黒くする
サブグラフで回転速度を制御する
Linear Dragだと回転速度を制御できないので、サブグラフを作成する必要がある。参照サイト
指定した位置にエフェクトを設定する
下の例でいうと、指定した位置にMeshRenderオフのモデルを配置しそれをSet Positionに設定する。
下の例は、分かりやすくするため球体を描画しているが実際は非表示にしてください。
Get AttributeのCurrentとSourceの違い
Currentは、Initialize ParticleコンテキストやSpawnコンテキストで設定した値を使用する。
Sourceは、更新された値を取得する。
下の例でいうと、CurrentだとInitialize Particleコンテキストで設定したVelocityが取得しているので、ダーツがそのまま進んでいる。
Sourceは、Collide With Cone/Cylinderで衝突したパーティクルは消失し速度が失っているので、それを取得しておりその結果ダーツが止まってる。
Vertex、Edge、Surface(Random)、Surface(Uniform)、Surface(Barycentric)の違い
MeshをLODにして最適化を行う
Set SizeとSet Scaleの違い
パーティクルの最終的なサイズは、Size * Scaleになる。
Scaleは各軸を設定でき、Sizeはそれがでkない。
Output Event HandlersでVFXのイベント制御
まずPackage ManagerにOutput Event Handlersがあるのでインポートする。
参照サイト
カメラシェイク
VFXOutputEventCinemachineCameraShake.csのOutput Eventと
VFXGraphのOutput EventコンテキストのEvent Nameを同じイベント名にする。
カメラシェイクの仕方などはCinemachine Impulse Sourceで制御する。
物理演算
一応、Sampleには、VFXOutputEventRigidBody.csがあるが物理演算を与えたいオブジェクトを一つしか指定できない。
以下はそれらを改良したものである。
using UnityEngine.Events;
namespace UnityEngine.VFX.Utility
{
[ExecuteAlways]
[RequireComponent(typeof(VisualEffect))]
class OutputEventHandlerMultipleRB : VFXOutputEventAbstractHandler
{
public override bool canExecuteInEditor => false;
public enum Space
{
Local,
World
}
static readonly int k_Position = Shader.PropertyToID("position");
static readonly int k_Size = Shader.PropertyToID("size");
static readonly int k_Velocity = Shader.PropertyToID("velocity");
[Tooltip("The Rigid body to apply a force on.")]
public Rigidbody[] rigidBodies;
[Tooltip("The Space VFX Attributes values are expressed.")]
public Space attributeSpace;
public float UpwardsModifier = 1.0f;
public enum RigidBodyEventType
{
Impulse,
Explosion,
VelocityChange
}
[Tooltip("Type of Instantaneous Force to apply on the RigidBody upon event:\n - Impulse using the Velocity attribute \n - Explosion at given Position attribute, using the Size for radius and the magnitude of Velocity Attribute for intensity\n - Velocity Change using Velocity Attribute")]
public RigidBodyEventType eventType;
public override void OnVFXOutputEvent(VFXEventAttribute eventAttribute)
{
if (rigidBodies == null|| rigidBodies.Length == 0)
return;
var position = eventAttribute.GetVector3(k_Position);
var size = eventAttribute.GetFloat(k_Size);
var velocity = eventAttribute.GetVector3(k_Velocity);
if (attributeSpace == Space.Local)
{
position = transform.localToWorldMatrix.MultiplyPoint(position);
velocity = transform.localToWorldMatrix.MultiplyVector(velocity);
// We assume that the size is bound to the X component of the transform scale
// and that the transform is uniform.
size = transform.localToWorldMatrix.MultiplyVector(Vector3.right * size).magnitude;
}
foreach (var rigidBody in rigidBodies )
{
if (rigidBody == null)
continue;
switch (eventType)
{
case RigidBodyEventType.Impulse:
rigidBody.AddForce(velocity, ForceMode.Impulse);
break;
case RigidBodyEventType.Explosion:
rigidBody.AddExplosionForce(velocity.magnitude, position, size, UpwardsModifier);
break;
case RigidBodyEventType.VelocityChange:
rigidBody.AddForce(velocity, ForceMode.VelocityChange);
break;
default:
break;
}
}
}
}
}
Prefab生成
VFXOutputEventPrefabSpawn.csを使用すると、Prefabをイベント発火に合わせて生成できる。
Prefabの個数や、座標角度スケール生存期間をパーティクルに合わせられることができる。
下の例だとライトを生成している。
下の例はVFXOutputEventPrefabSpawn.csでRenderTextureで使用するパーティクル生成し、そのRenderTextureを使用してパーティクルを調整している。
VFX Property Binder
対象のオブジェクトの情報をVFXGraphでインプットできる機能
下記では、対象オブジェクトの座標をVFXGraph側でインプットとして読み込んで、座標として設定している。
参照サイトのp134、参照サイト
Event Binder
パーティクルの発生と停止を制御できる。
Mouse Event Binder
マウスの挙動によってパーティクルの発生と停止を制御できる。
Rigid Body Collision Event Binder
RigidBodyコンポーネントで衝突でパーティクルの発生と停止を制御できる。
Trigger Event Binder
Triggerの衝突でパーティクルの発生と停止を制御できる。
Visibility Event Binder
オブジェクトの表示・非表示によってパーティクルの発生と停止を制御できる。参照サイト
アトリビュート
アトリビュートはコンテキストをクリックすると、そのパーティクルの情報を記載されている情報のことである。
例えば、Set Sizeのブロックを追加すると
sizeのアトリビュートが追加されていることが分かる。
なお、各アトリビュートの詳細な情報は、参照サイトのp143以降を参考に。
また、ブロックを追加するだけでなく、Attributeを変更することでもアトリビュートを変更できる。
ブロックのインスペクター
ブロックのインスペクターについて記載する
Attribute
アトリビュートを変更できる。
変更前
変更後
Composition
Overrite
→アトリビュートを上書きする
Add
→既存のアトリビュートを加算
Multiply
→既存のアトリビュートを乗算
Blend
→Blendを調整して既存のアトリビュートとブレンドする(Lerpみたいなイメージ)
Source
Slot
ブロックの入力値をもとに。
Source
親パーティクルを継承する。
下の例だと親パーティクルの赤色を子パーティクルが継承していることが分かる。
Ramdom
Off
→パラメータをランダムにしない
PerComponent
→各要素ごとにランダム
RGBごとにランダム
Uniform
→各要素同ランダム
RGBごとに同じ値のランダム
複数のOutputコンテキストを使用する
何秒か遅れてパーティクル発生
ブロックの順番は正しくしないと意図しない結果になる
Set Velocity from Direction & Speed(Change Speed)をAdd Directionよりも前にブロック配置すると正しい挙動にならない。
理由はSet Velocity from Direction & Speed(Change Speed)はdirectionを参照しているため。
VFXGraphで頂点アニメーションを行うときは、ShaderGraphのSupport VFX Graphを有効にする
速度(Velocity)と速さ(Speed)の違い
速度
→大きさと向きを持った力(ベクトル量)
速さ
→向きを持たない力(スカラー量)
向き(direction)と角度(Angle)
向き
→速度ベクトルの向き
角度
パーティクル自体の描画に使用される角度
RandomとNoiseの違い
Randomは完全にばらばらなランダム
Noiseは規則性のあるランダム。
SDF Bake Tool
SDFとは、オブジェクトの表面からの距離を格納した3Dテクスチャテータである。
SDFの作成方法は、HoudiniとUnity上で作成可能である。
今回は、Unity上のSDF Bake Toolについて述べる。
Point Cache Bake Tool
Point Cacheは座標、色、法線の情報が格納されたもの。
Point Cache の作成方法は、HoudiniとUnity上で作成可能である。
今回は、Unity上のPoint Cache Bake Toolについて述べる。
Timelineの開始と終わりとで、VFXGgraphのパーティクルの発生終了制御する
TimelineのName
VFXGgraph
パーティクルが重なっているアーティファクトを、Timelineでパーティクル発生の開始時間ずらして解消する
パーティクルが重なっているアーティファクト
アーティファクトを解消した動画
同じVFXGraph内で複数のエフェクトがある場合で、一つだけ再生したい場合
Spawn systemのブロックのチェックを外す。
SubGraph
SubGraphを使用すると、同じような処理をまとめることができる。
サブグラフ前
サブグラフ実施
Convert To Subgraph Operator押下
ファイル名入力
完成
スクリプトでVFXGraphを制御
TimelineとVFXGraphの連携
ShaderGraphとVFXGraph
VFXGraph使用する上で設定すべき項目
Experimental Operators/Blocks
有効にすべき。
カスタムアトリビュートとShaderGraphを使えるようにするため。
Show Additional Debug info
有効にすべき。
色々な情報が確認できるようになる。
無効
有効
パフォーマンスをプロファイルできる
SDFとポイントキャッシュ周り
VFX ToolBox
Houdiniからポイントキャッシュやベクターフィールド出力して、VFXGraph上で使用できる。
Unity Grenobleでタイリング可能なシームレステクスチャ作成可能
Debug modesが出てこない時の解消法
Debug modesが出てこない時の解消法は、Reset All LayoutsでUIをリセットすれば解消できた。
途中でノードを繋げたい場合、一々ノードを外さなくてよい
削除したプロパティをBlackboardから分かりやすくする
エディタ上で、パーティクル再生をスローや早送りにする
「Set→」でパーティクル再生速度を変更できる。
エディタ上の便利な機能
フリーラインで選択
Shift + 右クリック
コンパイル行わずエフェクト再生
F5
コンパイル行ってからエフェクト再生
F7
サブグラフで複雑な処理をまとめたり、使いまわしたりできる
エフェクトを作成する際は大きさの指標となるオブジェクトを置いて作業すると良い
例えば1mと10mの炎だとテクスチャに求められるディテールが変わってきたりする。
また、スケール感が分かればそれにあったリファレンスも探したりしやすくなる。
Discussion