Gaming Life

一日24時間、ゲームは10時間

UE4 Niagaraを触ってみる(3) 引き寄せ(Repeller)モジュールを自作

 シリーズNiagara第三弾。前回記事はこちら。

ai-gaminglife.hatenablog.com

 前回、パーティクルを引き寄せるアトラクタを作った。今回はその逆。パーティクルを払いのけるような動きをする「リペラー(Repeller)」モジュールを作成した。

完成品

環境

UE4.20 preview5

参考にしたサイト

 Nature of Code -Processingで始める自然現象のシミュレーション- のp148以降に紹介されているアルゴリズムを流用。

Nature of Code -Processingではじめる自然現象のシミュレーション-

Nature of Code -Processingではじめる自然現象のシミュレーション-

 こちらの本は英語版が無料で公開されており、全ソースコードGitHubで公開されている。

 今回流用したアルゴリズムのProcessingソースコードこちら

Module Scriptの概要

全体図

f:id:ai_gaminglife:20180714121125p:plain

 万有引力公式で得られるベクトルに-1を乗じることで反発方向への速度ベクトルを取得している。

解説

f:id:ai_gaminglife:20180714121136p:plain

 Map Getで Partice.PositionとPartice.Velocityを取得。Particle.○○は各パーティクルが持つ変数のこと。

 続いてMap GetのModule -> Make New、もしくはParametersパネルのModuleから

  • Module.RepellerPoint
  • Module.DistMin
  • Module.DistMax
  • Module.Strength

を追加する。Module.○○はそのモジュールの中だけで使えるローカル変数で、エミッター編集画面で編集することが出来る。

 Module.RepellerPoint - Particle.Positionで反発点とパーティクルとの間のベクトルを取得できる。このベクトルをNormalize(正規化、長さ1のベクトルに変える)、Length(ベクトルの長さを取得)につないでおく。

f:id:ai_gaminglife:20180714121145p:plain

 反発点とパーティクルの間の距離を万有引力公式の距離に当たる部分に突っ込めば反発力が得られる。が、例えばRepellerPointと全く同じ位置にパーティクルが生成されるとそのパーティクルはずっと動かなくなり、RepellerPointとかなり離れた位置に生成されると、その距離の二乗で割ったものがパーティクルにかかる力となる都合上、殆ど動きがなくなってしまう。

 この問題を解決するため、反発点・パーティクル間の距離をある範囲に制限(Clamp)する。ClampのMinにはModule.DistMinを、MaxにはModule.DistMaxを使用する。

f:id:ai_gaminglife:20180714121154p:plain

 万有引力公式を使って得た力を反発点・パーティクル間ベクトルを正規化したものに乗じる。これは運動方程式に従うと、ある時刻での加速度に当たることがわかる。

 加速度がわかればあとはパーティクルの速度を更新するだけ。得られた加速度をParticle.Velocityに加え、Map Setで更新する。

 これで完成。ちなみに冒頭紹介した動画は、前回記事のもののアトラクタモジュールをリペラーモジュールに差し替えただけで、そのパラメータは

  • DistMax 100.0
  • DistMin 10.0
  • RepellerPoint 0.0, 0.0, 0.0
  • Strength 20000

に設定している。

あとがき

 引き寄せが作れたから反発を実装してやろうと軽い気持ちでつくったものだが超エモいエフェクトが出来た。Niagara、本当に面白い。

UE4 Niagaraを触ってみる(2) アトラクタ Module Script自作

 シリーズNiagara第二弾。前回記事はこちら。

ai-gaminglife.hatenablog.com

 パーティクルをある点に集めるアトラクタModuleを作った。

完成品

環境

UE 4.20 Preview5

参考にしたサイト

https://www.openprocessing.org/sketch/506554

 OpenProcessingというサイト。p5.jsやprocessingで記述されたジェネラティブアートがソースコード付きで公開されている。見ているだけで楽しいのでおすすめのサイト。

Module Scriptの中身

全体図

f:id:ai_gaminglife:20180712160319p:plain

 順に追っていく。

f:id:ai_gaminglife:20180712160327p:plain

 Parameters->Moduleから

  • Vector AttractorPoint
  • Float DampingCoefficient
  • Float RangeOfTheNoEffect
  • Float Strength

を追加。Module.○○のパラメータはローカル変数のような振る舞いをし、Map GetするとEmitter編集画面で制御出来るようになる。

 今回はパーティクルそれぞれの位置と速度ベクトルが必要なのでそれもMap Getする。

f:id:ai_gaminglife:20180712160336p:plain

 AttractorPointからParticle.Positionを引き、Lengthノードにつなげることで引き付ける点と個々のパーティクルとの距離を求めることが出来る。ここから万有引力の公式に従い

(強さ係数)×(引きつけ点までのベクトル) / (引きつけ点までの距離の二乗)

でこの時刻での加速度を求められる。

 引きつけ点までの距離が "RangeOfTheNoEffect" 未満の時は速度を0に、そうでなければ前の速度に求めた加速度を加えた値を速度とする。

f:id:ai_gaminglife:20180712160345p:plain

 求めた速度に更にDampingCoefficientを乗じたものをMap SetでPartice.Velocityに戻す。

 これで、

引きつけ点から半径RangeOfTheNoEffect以上なら引きつけ点に引きつけられ、未満になると速度がゼロに更新されるモジュールが完成した。

パラメータ例

  • DampingCoefficient 0.95
  • AttractorPoint (0.0, 0,0, 0.0)

を固定し半径1000の球内に100ずつパーティクルをスポーンさせる

RangeOfTheNoEffect = 100, Strength = 20000

f:id:ai_gaminglife:20180712160353g:plain

RangeOfTheNoEffect = 100, Strength = 200

f:id:ai_gaminglife:20180712160423g:plain

RangeOfTheNoEffect = 500, Strength = 20000

f:id:ai_gaminglife:20180712160425g:plain

UE4 Niagaraを触ってみる(1)

 そろそろ正式実装されると一部で噂のUE4の新パーティクルシステムNiagara。現時点では英語情報すらほぼ無く、手探りでやっていくしかない。が、UE4.20のPreview版時点では前バージョンと比較してもかなり使いやすくなっているのでチョットずつ触り始めている。

 多くの人に触ってもらって情報共有されることを期待して、基本的なことばかりになってしまうがNiagaraに関する記事も書いていこうと思う。

環境

UE4.20 Preview5

Niagaraを有効にする

 現段階では実験的機能で、プラグイン扱いとなっている。有効にするにはプラグイン -> FXのNiagaraをEnabledにしなければならない。

 Niagara Extrasは必須ではないが、参考になるNiagara EmitterやNiagara Module Scriptが用意されている。今回作るエフェクトではこちらに用意されているスクリプトを流用するのでEnabledにする。

f:id:ai_gaminglife:20180711173345p:plain

 再起動後、プラグインに含まれているアセットを見たい時は、コンテンツブラウザのView OptionsでShow Plugin Contentにチェックを入れる必要がある。

CascadeNiagaraの違い

 これについてはこちらの記事がとても詳しい。

papersloth.hatenablog.com

 ここでも簡単な解説を。

従来のCascadeの編集画面。

f:id:ai_gaminglife:20180711173357p:plain

 CascadeではEmitterという一つの塊に寿命、初速度、加速度、色といった予め用意されているModuleを追加する。そうして作った複数のEmitterで一つのエフェクトを作っていた。

 一方Niagara。これはコンテンツブラウザのFX->Niagara Emitterで追加できるNiagara Emitterの編集画面。

f:id:ai_gaminglife:20180711173407p:plain

 大元にある

  • Emitter Spawn
  • Emitter Update
  • Particle Spawn
  • Particle Update
  • Render

というモジュールが Niagara Module Script からの入出力を受け取り、寿命、初速度、加速度、色等を制御する。

 大きな違いは

  • NiagaraはEmitterをそれぞれ別ファイルとして保存できる
  • モジュールをノードベースでプログラマブルに制御出来る

こと。

 NiagaraNiagara Emitterという形でEmitterを別ファイルとして保持する。そして個別に作られたEmitterは Niagara Systemでまとめて管理され、ここで一つのエフェクトが完成する。

 こちらはNiagara Systemの編集画面。NE_CircleGeneというNiagara Emitterを2つ持ち同時に再生することで一つのエフェクトとなっている。

f:id:ai_gaminglife:20180711173418p:plain

 そしてNiagaraではモジュールをノードベースでプログラマブルに制御出来る。ここがNiagara最大の特徴と言える。

 Niagara Emitter内でSelected Emitter Graphを見てみるとこのようなノードベースのコードが見られる。

f:id:ai_gaminglife:20180711173429p:plain

 これは先程見せたNiagara Emitterのモジュール編集画面(Selected Emitters Tab)と対応しており、Graphを編集するとSelected Emittersが、Selected Emitterを編集するとGraphが対応して自動で変更される。

(ブログ資料製作中、Emitter Graphを誤って消したところ、前バージョンにはあったはずのWindow -> Selected Emitter Graphが消えていて再起動するしか再び表示させる方法がなかった。不具合?)

 ノードベースの編集が可能になったことでCascadeでは実現できなかったプログラムチックな動きを実装できる。

 勿論このモジュールも再利用できる。例えばパーティクルに重力を与えたい、と思ったらコンテンツブラウザでNiagara Module Scriptを追加し、ここでその制御を実装する。一度作ったNiagara Module ScriptはどのEmitterでも利用可能。プログラマが複雑なModule Scriptを用意し、デザイナーがそのModuleを組み合わせて一つのEmitterを作る……といったことができるようになる。

Niagara Module Scriptの編集画面

f:id:ai_gaminglife:20180711173438p:plain

Niagaraを使ってみる

 今回はNiagara Extrasに用意されているEmitterを利用して作っていく。

 NiagaraExtras Content/Emittersに入っているEmitterを自分のコンテンツフォルダの中にコピーして入れる。そのEmitterを開くとおそらくこの様なエフェクトが見れるだろう。これだけでも圧巻。

f:id:ai_gaminglife:20180711173451p:plain

パーティクルに重力をかける

Selected Emittersタブ上でParticle Updateの右側にある+マークをクリック。Acceleration Forceを検索し追加する。このままではエラーが出るのでドラックアンドドロップでSolve Force and Velocityの上に表示されるようにする。

f:id:ai_gaminglife:20180711173506p:plain

Acceleration Forceは標準で用意されているModule Scriptでパーティクルに加速度を与えることが出来る。

Module Scriptを編集する

 デフォルトのままだと同じ方向にぐるぐる回るようにパーティクルがスポーンされている。これはParticle Spawnに設定されている Point Spiral Location Moduleで計算されている。ここではこのScriptを改造してこの回転方向を制御出来るようにする。

 Graph上でPoint Sprial Locationを見つけダブルクリック。するとPoint Spiral Locationの編集画面に移れる。

 Map Getの右側のプラスピンを押し Module -> Make New -> Floatと選択しModule.RotDirectionという名前の出力ピンを追加する。自動で入力ピンも用意されるが0.0という値が表示されていると思う。これはデフォルトの値を意味する。今回は1.0と設定しておく。

f:id:ai_gaminglife:20180711173518p:plain

 このRotDirectionをMap SetのParticles.Velocityにつながっている値と掛け合わせる。

f:id:ai_gaminglife:20180711173530p:plain

 Emitter編集画面に戻ってSelected EmittersタブにあるPoint Sprial Locationを見てみると、新たにRotDirectionという数値を設定する枠が用意される。この値を1.0にすれば順回転、-1.0に設定すれば逆回転させることが出来る。

Niagara Systemにまとめる

 コンテンツブラウザでNiagara Systemを追加。最初の段階では何も表示されていない。Timelineの +Track を選択して先程作ったEmitterを追加できる。今回は作ったEmitterを2つ追加する。

f:id:ai_gaminglife:20180711173538p:plain

 Timelineで選択したEmitterのパラメータは、これまでと同じくSelected Emittersタブで制御出来る。

 最初に追加したEmitterは、RotDirection 1.0に、次に追加したEmitterはRotDirection -1.0に設定すると、順回転、逆回転する2つのEmitterが同時に発生する。

 Particle Update内の Set VariablesタブでParticle.Colorを赤と青に設定するなどするとこんな遺伝子のようなParticleの完成。

まとめ

 比較的簡単に、Cascadeでは難しかったであろうエフェクトが作れた。一部標準実装のModule Scriptのコンパイルが通っていないのにエフェクトは正常に動作するなど怪しい部分もあるが、今回の作業中にクラッシュすることは一度もなかった。正式版も近いかも……?  

UE4 メッシュの一部の色をBPで動的に変更する

 以前の記事でマテリアルエディタ上で一部の色だけを切り替える仕組みを作った。で、折角だしBlueprint上でパラメータを切り替えられるようにしようと試してみた。

ai-gaminglife.hatenablog.com

動的にマテリアルのパラメータを制御するBPを作る

f:id:ai_gaminglife:20180706191606p:plainf:id:ai_gaminglife:20180706191608p:plainf:id:ai_gaminglife:20180706191612p:plainf:id:ai_gaminglife:20180706191616p:plain 

 詳細は省くが、これでBlueprint上でマテリアルで設定したパラメータを制御出来るようになる。今回は設定したBoxCollisionにOverlapしたら"SwitchJumpMaterialColor"でマテリアルで設定したboolパラメータ、"IsJump"を切り替えることで色を変える、といったことをしている。

f:id:ai_gaminglife:20180706191659p:plain

 で、そのSwitchJumpMaterialColor関数を作っている時にある問題に気づく。

f:id:ai_gaminglife:20180706191714p:plain  Bool ParameterをSetするBPが、ない。

解決策

 考えてみたら当然のことで、マテリアル上で用意したboolパラメータIsJumpは正確に言うと、Static Bool Parameter、つまり静的なbool変数だったのだ。静的変数を動的に変更することなぞ出来ない。Dynamic=動的に変更が出来るマテリアルパラメータは

の3つのみの模様。というわけで今回はScalar(=float型変数)パラメータで色を切り替えられる様にしてみた。

f:id:ai_gaminglife:20180706191724p:plain

 Scalarパラメータ"IsJump"を0-1にClampし、その値で元のテクスチャと一部の色を変更したテクスチャを線形補間している。これでIsJumpが0なら元のテクスチャが、1なら変更後のテクスチャを表示させることが出来る。

 で、実際パラメータを制御する関数は画像の通り。

f:id:ai_gaminglife:20180706191733p:plain

 これで動的に色を切り替えることが出来るようになった。

Substance Painter2018でUV境界で色がにじむ問題が解決した話

 以前の記事でSubstancePainter2018でローポリに塗りつぶしレイヤを使ったベタ塗りをするとUV境界で色がにじむ問題が発生していた。

ai-gaminglife.hatenablog.com

 どうやらこれはSP2018から塗り方が変更されたのが原因だったらしい。しかし最新ver、Substance Painter 2018.1.3でこの問題に対する解決策が用意された。

TEXTURE SET SETTINGのUV paddingがデフォルトでは"3D Space Neighbor"になっている。これを"UV Space Neighbor"に変更。これで滲みが解消される。

  • 3D Space Neighbor

f:id:ai_gaminglife:20180706012122p:plain

  • UV Space Neighbor

f:id:ai_gaminglife:20180706012130p:plain

デフォルトになっている3D Space Neighborは何の為に用意されているのだろうか……

Python リストの最後を取得する

 len()とかを使うのもありだが簡単に取得する方法があったのでメモ。

list = [ 'A', 'B', 'C', 'D', 'E']
print(list[-1])     #リストの最後の要素を表示する
print(list[-2])     #リストの最後から2番目の要素を表示する

 最近大学の実習でPythonを使っているがC++と随分書き方が違い戸惑う…… const参照渡しとかないのかなあ。

UE4 メッシュの一部の色だけをパラメータで切り替えられるマテリアルを作る

unrealengine.hatenablog.com

 上記のブログ等で物体全体の色をパラメータで切り替えるなどは紹介されているが一部だけの色を切り替えるみたいなものは見つけられなかったのでそれを自前で実装した。マテリアル全体の構成は以下の通り。

 ちなみに今回、マテリアルはSubstancePainterで作成した。

f:id:ai_gaminglife:20180704015038p:plain

テクスチャの色域を指定してマスクテクスチャを作る

f:id:ai_gaminglife:20180704015051p:plain

 Photoshop等でマスクテクスチャを用意するのが最も簡単だろうが今回はマテリアルエディタ内でマスクテクスチャを作ってみる。

 抜き取りたい色を "Const3Vector"で用意。それを "Distance"のBに繋ぐ。

 このままではグレーの部分が出てしまうのでifノードを使って0と1でくっきり分ける。これで紫部分をくり抜けるマスクテクスチャを作ることが出来る。

一部分だけ色を変更したテクスチャを作る

f:id:ai_gaminglife:20180704015100p:plain

 "JumpColor"という3Vectorパラメータを作成。この色で紫部分を塗りつぶす。

 生成したマスクテクスチャと"JumpColor"を掛け合わせ、反転させたマスクテクスチャと元々のBaseColorテクスチャを掛け合わせたものを足すことで一部だけを"JumpColor"で塗りつぶすことが出来る。

Switchでもとの色と塗り替えた色を切り替える

f:id:ai_gaminglife:20180704015108p:plain

 Static Boolパラメータ、"IsJump"を用意。これをSwitchノードのValueに繋ぎ、Trueに"JumpColor"で一部を塗りつぶしたテクスチャを、Falseに元々のテクスチャを繋ぐ。

 これでIsJumpの切り替えで一部の色だけを切り替えるマテリアルが作れた。

f:id:ai_gaminglife:20180704015116p:plainf:id:ai_gaminglife:20180704015120p:plain

(続き)

ai-gaminglife.hatenablog.com