Typescriptにおけるカラーコードの文字列型の定義方法 - typeとinterfaceの比較と使い分け

カラーコードを入れるための変数の型を定義したかったんだけど、interfaceとtype どちらを使えばいいか曖昧だったのでまとめといた。

Typescriptでカラーコードの文字列を扱う変数の型を定義する方法には、typeとinterfaceの2つのアプローチがあるが、それぞれの違い 向き不向き どちらを使うべきか。

1.-typeを使う

type ColorCode = string;

typeキーワードを使用して型エイリアスを定義。ColorCodeはstring型の別名として定義される。

type ColorCode = `#${string}`;

テンプレートリテラルを使用することで、カラーコードの文字列を#で始まるものに制約することができる。 この書き方だと#から始まる文字列ってことしか制限できないけど、とりあえず大体の制限は設けられる。

2- interfaceの使用

interfaceを使用してオブジェクトの形状を定義。ColorCodeはvalueプロパティを持つオブジェクトの形状を表jsu。この方法では、カラーコードを表すオブジェクトを宣言し、valueプロパティにカラーコードの文字列を格納する。

interface ColorCode {
  value: string;
}

interfaceの利点:

カラーコード以外の文字列を受け入れない制約がある(あとから拡張とかできない)。 オブジェクトの形状を詳細に制御できる。 interfaceの制限:

シンプルな型エイリアスよりも記述が煩雑になる場合がある。 実際にこの型で宣言した変数に値を代入しようとすると

const color:ColorCodes = {value: '#000000'}

というオブジェクトになってしまい冗長な感じになる。また制限をがかけられないので、別途ベリデーションを作る必要がある。

interface ColorCode extends String {}

という風にもできるけど、多少の制限がワンラインでかけられるtype使う方が今回はよさそう

PlantUMLで項目名に括弧とかの記号を使いたい時

記号を含めたテキストを項目名とかで使いたい時は

"文言(注釈)"

って感じで項目内のテキストを丸ごとダブルクォートで囲う。シングルクォートでもいけた。

TypeScript、ここ2年くらい一切書いていなかったので思い出すためにも軽いWebアプリをNext.jsで作ろうとしてる。なんならNext.js自体は初めて触るから色々調べつつ書いてる。

数年前までと本当にWebフロントの環境が変わってて浦島太郎状態になってる。公式でCRAが非推奨になってたのは本当にびっくりした。

まだNext.jsのディレクトリ構成の仕様とかが把握しきれていないので本当に手探り状態。

せめてサービスの流れだけは見失わないようにPlantUMLでシーケンス図をメモしておいてる。

【UE4.26】NiagaraのAgeについて

この記事は Calendar for Unreal Engine (UE) | Advent Calendar 2021 - Qiita 2 の14日目の記事です。13日目の 独自のタブをエディタのメニューから呼び出す方法 - Qiita は、最近独自の自作ツールを作ったりしてたりしてたので個人的にホットな記事で 参考にさせてもらおうと思っています。


なにについて書くか

Niagaraでパーティクルの大きさや色を変えたりする時に使っている "CurveIndex"に設定する値には"~~~Age"ってのがよく使われると思います。
これについて整理しました。自分自身、Niagaraでパーティクルを作ろうかなって始めた時に知りたかった情報でもあるので 初心者の人に見てもらえると嬉しいです。

今回は、普段自分がよく使うSystem系、Emitter系、Particle系について調べました。

その他のAge系についてはよくわからんなのでいずれ...。

自分自身、理解の及んでいないところもあるので、実際の動きを見ながら検証して確認していきました。


Niagaraでパーティクルを作成する際に、「パーティクルの更新」や「エミッタの更新」の場所で、カーブ等の値を設定する時があると思います。

f:id:ten0313:20210912131141p:plain

例えばこれは、"ScaleColor"の"ScaleAlpha"の値をカーブにして設定しているもので
時間軸(横軸の値)0から0.5にかけて指定の値(縦軸の値)を1に増加、その後 時間が1にかけて0に指定の値を現象させています。

"エミッタの更新"欄で、"Spawn Burst Instantaneous"のSpawnCount"を1に設定して、パーティクルをひとつスポーンさせます。

"パーティクルのスポーン"内の"Initialize Particle"の"Lifetime"を5.0に設定して、パーティクルの寿命を5秒に設定して動かしてみます。

また、Lifetimeに設定した時間が来ても パーティクルが消滅はしないように"ParticleState"内の"Kill Particles When Lifetime Has Elapsed"のチェックを外しています(ライフタイム後の挙動まで見たいからです)。


5秒毎に点滅しているのがわかります。
もうちょっと詳しく書くと、2.5秒かけて最大まで明るくなり、その後 2.5秒かけて暗くなっていっています。

この時、時間の値には0から1までの指定しかしておらず、5秒の制御をしているとは思えません。
多分、パーティクルの一生を(スポーンしてからキルされるまで)割合的に0から1にしてやるんだと思いますが、もっと詳しく 他の時間の指定方法等も含めて調べていきます。

(このカーブの指定方法、自分が勉強してた時は「0から1の割合内で考えてカーブのポイント打っていってね」って指示が多くて よくわからんままつかっていました)

 

最初に 今回、検証用に使うパーティクルのマテリアルを紹介しておきます。

f:id:ten0313:20211214133047p:plain

NiagaraSystemからマテリアルの数値をいじった事がわかりやすいように、入力された数値をそのまま表示できる(主にデバッグ用に使われることを想定されたマテリアルノードですが)DebugScalarValuesにDynamicParameterをつないだマテリアルを用意しました。

これで、Niagaraから"Dynamic Material Parameters"を使ってマテリアルにどのような数値が入力されているのかわかりやすくなります。

f:id:ten0313:20211213224549p:plainこんな風に。

 

まず、Particle系の値からあてはめてみていきます。


なお、今回の検証では 

Systemの"LoopDuration"を5.0

f:id:ten0313:20211214134030p:plain

Emitterの"LoopDuration"を4.0

f:id:ten0313:20211214134138p:plain

Particleの"LifeTime"を3.0にしています

f:id:ten0313:20211214134241p:plain

これらは確認の際に必要に応じて無効にしたりLifeCycleModeを変更したりはしますが、値として利用する場合は上記の通りにして動かしていきます。

Particleç³»

上から順に、"Particle.Age"、"Particle.NormalizedAge"を入れています。

Particle.Ageの方は3秒間かけて0から3に増加、Particle.NormalizedAgeの方は3秒間かけて0から1に増加していっています。

Ageは単純にパーティクルがスポーンしてからの経過時間(正確にはLifeTimeが切れるまでの時間)を表わしており、NormalizedAgeの方は言葉の通り Ageをノーマライズ(0から1の間にスケールさせた(正規化))した値のようです。

f:id:ten0313:20211214135821p:plain

パーティクルがスポーンされるまでの時間にディレイを持たせてみました。
待機の1秒が経過した後に、スポーンし 0からカウントが始まっているのがわかります。

Particle.NormalizedAgeを利用して色を変えています。
スポーンされた時には青のパーティクルが、消える時間(LifeTime)を迎える毎に赤色になっていっています。

Emitterç³»

上から順に、"Emitter.Age"、"Emitter.LoopedAge"、"Emitter.NormalizedLoopedAge"を入れています。

f:id:ten0313:20211214141300p:plain

また、ParticleStateのLoopParticlesLifeTimeのチェックを外してParticleがLifetimeを過ぎても消えないようにしました。

Ageの方はSpawnしてからの時間が表示されています。

LoopedAgeは、EmitterのLoopDurationとして設定した4秒の時間が過ぎたら、また0からカウントされている値が表示されているようです。

NormalizedLoopedAgeには、4秒間かけて0から1までの値が入っているようです。

Particle.NormalizedAgeを利用して色を変えていっています。パーティクルのスポーンされたタイミングに関わらず、時間経過により一斉に色が変化しています。

 

Systemç³»

上から順に、"System.Age"、"System.LoopedAge"、"System.NormalizedLoopedAge"を入れています。

Ageはパーティクルシステムが始まってからカウントが始まっており、
SystemのLoopDurationは5.0を指定しているので、System.LoopedAgeはカウントが始まってから5秒経過後、また0秒からカウントする値が入っています。

NormalizedLoopedAgeはLoopedAgeを正規化した値が入っています。

FountainをベースにしたEmitterを複数用意して、スポーンの位置と出現のタイミングをずらしてみました。

f:id:ten0313:20211214154615p:plain

System.NormalizedLoopAgeに応じて色が変わるようになっているので、エミッタの出現タイミングに関わらず、一斉に色が変化するようになっているのがわかります。

以上です。

 

なにかわかりにくい事があったり、間違いがあればTwitterのDMとかにおねがいします。


[ この記事はブログ投稿者の憶測や考えによりつくられています。

よって書いてある内容に誤りや言い間違いがあるかもしれません。もし修正したほうがいい場所や「こういった言い方のほうが”ソレっぽい”よ」などがありましたら後に記載してあります、リンク先のツイッターアカウントに教えてくださると嬉しいです:) ]

【UE4 .26】音とパーティクルを連携させてみる

この記事でわかることです。

  • グニョグニョ動く球に使ったマテリアルの作りかた
  • ワイヤフレームのみを描画するマテリアルの作りかた
  • Wavファイルから流れる音量値をパーティクルに伝える方法

今回の記事内で解説した内容で作ったパーティクルが下のツイート内の動画になります。十字部分やクルクル回るエミッタの所等の作成方法については、過去の解説記事で作ったものを流用してたりするので 今回は書きません(要望があったら詳しく書きますが、基本的には他の書かれた記事を参照していただけるといいかと思います)。

 

グニョグニョ動く球に使ったマテリアルの作りかた

"SimpleGrassWind"ノードを使います。

f:id:ten0313:20210702183246p:plain

本来、葉っぱや旗等に使うマテリアルに起用して 風に揺れるオブジェクトを表わしたりするものです。これを球に使うことで、グニョグニョ動くようにさせます。


繋げ方はこんな感じです。"WindIntencity"と"WindWeight"ノードに与える値の変化でグニョグニョの強さを変えます。

 

これでグニョグニョするようになります。

f:id:ten0313:20210702183949p:plain

Niagaraからグニョグニョの強度を変えられるようにDynamicParameterノードに繋げておきます。

 

ワイヤフレームのみを描画するマテリアルの作りかた

f:id:ten0313:20210702184421p:plain

これを作る方法です。
色んな方法があると思うんですけど、一番簡単な方法で僕はやりました。

f:id:ten0313:20210702184536p:plain

マテリアルの詳細から、"Wireframe"にチェックを付けます。以上です。

さっき作ったグニョグニョマテリアルの"Wireframe"をチェックしてみると

f:id:ten0313:20210702184710p:plain

こんな風になりました。

 

Wavファイルから流れる音量値をパーティクルに伝える方法

音に応じて動くパーティクルに絞って作ります。

 これを作ります。

使用するマテリアルはなんでも良いです。

f:id:ten0313:20210702185520p:plain

自分はコレを使いました。"RadialGradientExponential"ノードを使用して二重丸を描画したマテリアルです。

f:id:ten0313:20210702185640p:plain

システムの概要です。"Empty"を基に作りました。重要な所を説明していきます。

 

f:id:ten0313:20210702185727p:plain

Spawn Burst Instantaneous

10個のパーティクルを一気にスポーンさせます。

 

f:id:ten0313:20210702185823p:plain

パーティクルのスポーン

ここは特に特別な事はしていません。"(パーティクル) SpriteFacingを設定"でスプライトパーティクルの向きを上向きにして、"(パーティクル) SpriteAlignmentを設定"でカメラに対する角度を固定させます。

後は色を赤にしました。

 

最初の二つのパーティクルに関しては、モジュールに含まれていないので

f:id:ten0313:20210702190056p:plain

パラメータの中のパーティクル属性にあるのをみつけて、システムの概要の方にドラッグ&ドロップします。

 

パーティクル属性の中になかったら、右上の+ボタンを押して

f:id:ten0313:20210702190254p:plain

検索して追加します。

 

f:id:ten0313:20210702190331p:plain

"パーティクル更新"にパーティクルの動きをつけるモジュールを追加します。
"NMS_MoveDepthPosition"です。

これは最初から用意されているものではない、自作したものです。

作っていきます。

 

f:id:ten0313:20210702190829p:plain

NMS_MoveDepthPosition

マップ取得で、パーティクルの移動を受けとるVector型のピンと パーティクルシステムの位置を取得する"(エンジン)(オーナー)Position"を +ボタンを押して追加します。

その後、写真の通りにノードを組みます。

内容はコメントの通りです。入力されるVector型にパーティクルのインデックスを表わす"Execution Index"を乗算して新しいパーティクル程位置の差が大きくなるようにします。

それとパーティクルをスポーンさせた座標である"(エンジン)(オーナー)Position"と加算させます。 "Map Set"ノードに"(パーティクル)Position"を追加してそこに加算した内容を繋げて完成です。

 

NiagaraSystemの方に戻ります。

f:id:ten0313:20210702191744p:plain

公開されたユーザーにfloat型の値を追加して"VoicePower"と名付けておきます。

パーティクルと音を流すアクターを後で作成するのですが、そこからこのfloat変数を操作することになります。

f:id:ten0313:20210702192140p:plain

さっき作ったNiagaraモジュールをパーティクルシステムに追加します。
今回は高さを動かしたいので、Z軸の場所にさっき作ったユーザー変数を追加します(少し値を大きくしたかった(動きを大きくしたかったので)MultiplyFloatで2を乗算しています)

これでパーティクルの方は完成です。

パーティクルと音量を連携させるのを作っていきます。

 

f:id:ten0313:20210702195123p:plain

アクターを作成し、NiagaraSystemComponentとAudioComponentを追加します。

 

f:id:ten0313:20210702200347p:plain

NiagaraのNiagaraSystemAssetにさっき作ったパーティクルをセットします。

 

f:id:ten0313:20210702195108p:plain

AudioComponentに使いたいWavファイルを設定します。自分は文章の読み上げがわかりやすいと思ったので(楽曲よりも、単純な読み上げ音声とかの方が音量の抑揚が大きくビジュアライズ化した時にわかりやすいと思います)

coefont.studio

ここを使いました。とても自然な読み上げ音声を作成して、簡単にWavファイルにしてダウンロードできるので便利でした。

f:id:ten0313:20210702195642p:plain

AudioComponentの詳細内にある"On Audio Single Envelope Value"を追加します(緑の+ボタンを押します)。

 

f:id:ten0313:20210702195819p:plain

このイベントノードからは、現在流れている音の大きさがEnvelopeValueから出てくるようになっています。

それを"Set Niagara Variable(Float)"に繋げて、NiagaraComponentのユーザー変数である"VoicePower"に渡します。

 

これで完成です。

 このようにできたでしょうか。

 

なにかわかりにくい事があったり、間違いがあればTwitterのDMとかにおねがいします。


[ この記事はブログ投稿者の憶測や考えによりつくられています。

よって書いてある内容に誤りや言い間違いがあるかもしれません。もし修正したほうがいい場所や「こういった言い方のほうが”ソレっぽい”よ」などがありましたら後に記載してあります、リンク先のツイッターアカウントに教えてくださると嬉しいです:) ]

【UE4 .26】警告アラート的なHUD風パーティクルをNiagaraで作る

 コレを作ります。

 

まず、このパーティクルを作る上で要素を分けます(作成する過程が一緒で少し中の数値をいじったものをまとめます)。

 

 パーティクルを単純に回転させているものです(使っているマテリアル等に関しては後述します)。

 

 丸い円が広がりながら上昇してフェードアウトしていくものです。

 

 「緊急」の文字のついたパーティクルがランダムにスポーンされアニメーションするものです。

 

ひとつめから説明していきます。

 

 パーティクルを単純に回転させているもの

 

f:id:ten0313:20210626085932p:plain

やっている事は、真四角の平面メッシュに表示させたいマテリアルを張りつけて回転させているだけです。

基本はEmptyからエミッタを作成してMeshパーティクルを設定し、設定を少しいじっているだけなので特別なことはしていません。最低限、必要なモジュールを説明すると

 

f:id:ten0313:20210626100421p:plain

Initialize Particle

PositionMode内のPositionOffsetのZ軸を変更させ、高さを変えています。
また、MeshAttributesのMeshScaleModeをUniformに設定して数値を1.2にしてサイズを変更しています。

f:id:ten0313:20210626090711p:plain

SpawnBurst_Instantaneous

SpawnCountに1を設定することで、パーティクル生成時にひとつだけスポーンされます。(このモジュールと設定は今後説明するエミッタ達でも基本共通して追加してあります)

 

f:id:ten0313:20210626091044p:plain

Color

色の設定をしています。今回作るパーティクルでは、共通する色を持ったエミッタが複数存在しているので ひとつの場所から一括で変更できるようにした方が、調整が楽です。ユーザー属性の場所に色の情報の値を保持させてそれぞれのエミッタに設定しています。(システム属性で良いとも思いましたが、後々ゲーム内などで扱う際に外部から変更できた方が使い勝手が良さそうだなと思ったので...)


ユーザー属性にパラメータを追加する方法を書きます。

f:id:ten0313:20210626092026p:plain

「パラメータ」ウインドウから「公開されたユーザー」の横の+ボタンをクリックしてcolorと入力し、「Liner Color」を選択します。設定した値をエミッタに適用させたい場合は、追加した値をエミッタ内のモジュールにドラッグアンドドロップすればOKです。

 

各エミッタで共通する色の情報等の変数を持たせておくと、一括で変更できるので 調整、後々の変更などがしやすくて便利です。

f:id:ten0313:20210626093614p:plain

Particle State

一定時間でエミッタが消えてしまわないように設定しました。

 

f:id:ten0313:20210626093150p:plain

Update Mesh Orientation

「パーティクル更新」に追加します。メッシュパーティクルにZ軸を基とした回転を加えています。

数値を正の値にしたり負の値にすることで回転の方向を変更できます。

 

f:id:ten0313:20210626101001p:plain

メッシュとマテリアルの設定の概要です。使うマテリアルは好きな物を使うといいと思います。

ten0313.hateblo.jp今回使ったマテリアルはこの記事内で作ったものを流用しています。

 

 輪状のパーティクルがサイズを変えながら上に上がっていくエミッターです。

f:id:ten0313:20210626102638p:plain

エミッタの概要です

かいつまんで解説していきます。

 

f:id:ten0313:20210626102947p:plain

Spawn Rate

SpawnRateを3に設定して、たえまなく連続的にスポーンしつづけるようにします。

 

f:id:ten0313:20210626103354p:plain

GravityForce

Z軸に正の値を入れて重力を上向きにかけました。コレで上昇するようになると思います。

 

f:id:ten0313:20210626105425p:plain

Scale Color

パーティクルの更新にScaleColorを追加しました。透明度を表わすalphaにカーブで数値を入力して色がフェードイン・フェードアウトするようにしました。

 

f:id:ten0313:20210626110151p:plain

Scale Mesh Size

パーティクルのサイズをカーブで更新するようにしています。写真ではスポーンしてから徐々に大きくなるようにしています。

 

 「緊急」の文字がポップアップするものです。

f:id:ten0313:20210626112723p:plain

使ったマテリアルです

内容は画像作成ソフトで作ったものをTextureSampleとか使って動かしたりしています。

どんな形でも大丈夫です。好みのを作ってください(なんならtextureSampleとParticleColorで繋げるだけでもそれらしくなるとは思います)

 

f:id:ten0313:20210626113011p:plain

エミッタの概要です。

内容を説明していきます。NiagaraEmitterのFountainを基に作成します。

f:id:ten0313:20210626113154p:plain

Spawn Rate

スポーンさせる量をこれで設定します。数値を調整することで、スポーンされる量等を変更できたりします。

 

f:id:ten0313:20210626113353p:plain

Cylinder Location

円柱状の場所を指定してパーティクルをスポーンさせるものです。
CylinderHeightとCylinderRadiusで平たい円柱(高さ10、直径100の円柱)を作って、その中にスポーンさせるようにしました。

OffsetでZ軸の数値を変更して、少し高い位置にパーティクル群が出るようにしました。

 

f:id:ten0313:20210626113713p:plain

Scale Sprite Size


Y軸方向の大きさをCurveで指定して、スポーンしてからキルされるまでに パーティクルがピコンと動くようにしました。キー補完を「ユーザー」にして

f:id:ten0313:20210626113832p:plain

出現した時と消える際に少し大きくなるようにすることでちょっとかっこよくしました。

 

f:id:ten0313:20210626113918p:plain

Scale Color

パーティクル上部にこのエミッタが多数出現するので、下にあるパーティクル達は重なって見えにくくなってしまいそうです。対策として、Alphaを少し小さくすることで半透明にしました。このエミッタ同士が重なった時にも効果を発揮するはずです。

 

f:id:ten0313:20210626114157p:plain

Sprite Renderer

最後に表示方法の選択です。AlighnmentとFacingModeを設定することで、プレイヤーのカメラの位置に依存することなく、一定の方向を向き続けてくれるようになります。

 

 これで完成です。

 

なにかわかりにくい事があったり、間違いがあればTwitterのDMとかにおねがいします。


[ この記事はブログ投稿者の憶測や考えによりつくられています。

よって書いてある内容に誤りや言い間違いがあるかもしれません。もし修正したほうがいい場所や「こういった言い方のほうが”ソレっぽい”よ」などがありましたら後に記載してあります、リンク先のツイッターアカウントに教えてくださると嬉しいです:) ]

 

東京高速戦術@VRゲーム制作 (@kousoku_tactics) | Twitter

【UE4 .26】Niagaraでサイバー風のパーティクルを作る方法

 これを作ります。

 

・角度の範囲を指定してマテリアルを減算する

UE4小ネタ : 円形ゲージの作り方 - ぼっちプログラマのメモ

 

・平面のメッシュをパーティクルにする

【UE4】4.25でNiagaraを使って魔法陣エフェクトを作ってみよう - アルゴンUE4&アプリ開発日記

 

・メッシュパーティクルの回転

www.youtube.com

 

今回作るパーティクルですが、Niagaraの方でやることはほぼないです。マテリアルで円を書いたり線を引いたりする事の方が多いです。

 

まずはNiagaraEmitterの方を作っていきます。
NiagaraEmitter、NiagaraSystem等がよくわからない方は

www.youtube.comこの解説動画がすごいわかりやすいのでオススメです。

 

今回作るパーティクルに使うNiagaraEmitterは4種類です。

 

NE_RotateLockArrow

 

NE_RotateArrowSquiz

 

 

NE_BorderCircle

 

 

NE_CoolUINumber

f:id:ten0313:20210611041548p:plain

 

 

今回のParticleには共通して平面状のメッシュを利用します。

f:id:ten0313:20210611043630p:plain

正方形のひとつの面を持ったメッシュを作成しておきます。UV展開等はそのまま正方形でやっておきます。
僕はBlenderで作成しましたが、シンプルな形状なのでなんのツールでも作れると思います。

23.gigafile.nu

一応GigaFile便でダウンロードできるようにしました。他ツールを使うのがめんどくさい時は使ってください。

 

作っていくエミッタ達は、ほぼ全て

  1. マテリアルを作成する
  2. 平面メッシュにマテリアルを張りつける
  3. エミッタ内でMeshRendererとしてスポーンさせて動かす(色を調整する)

といった流れで作っていきます。

 

ひとつめのNiagaraEmitterから説明していきます。

NE_RotateLockArrow

 

くるくる回る細い線です。
まずはマテリアルから作っていきます。

f:id:ten0313:20210611050400p:plain

やっていることとしては、真ん中に丸の穴の空いた図からその丸より大きい丸の形状を引いて 出来た円の線から角度を指定して切りとっています。

参考にしたもの:
・丸を描く

[UE4] [UMG] はじめてのマテリアル、円を描く|GiRAFFIC ARTS ジラフィックアーツ|note

・角度を指定して切りとる

UE4小ネタ : 円形ゲージの作り方 - ぼっちプログラマのメモ

 

作ったマテリアルをエミッタに利用します。

f:id:ten0313:20210611052528p:plain

エミッタの概要です。

基本的にエミッタの内容は使用するマテリアルを除いて、ほぼ共通した内容なので 詳しく説明します。

f:id:ten0313:20210611060410p:plain

Emptyを開始点に作ります。

エミッタの更新からです。

f:id:ten0313:20210611061011p:plain

SpawnBurstInstantaneousで最初に一度エミッタをスポーンさせています。

パーティクルのスポーン

f:id:ten0313:20210611062302p:plain

PositionModeをSimulationPositionに設定、PositionOffsetを有効化します。
Z軸を調整します。これはパーティクル上でエミッタをどの位置にスポーンさせるか(表示位置)を指定しています。

エミッタの色を指定するColorは後でNiagaraSystemの方にエミッタを追加した際に複数のエミッタに対してまとめて色の変数を追加して管理するので、今はいじらなくて大丈夫です。

 

パーティクル更新

f:id:ten0313:20210611063245p:plain

ParticleStateのKillParticlesWhenLifeTimeHasElapsedのチェックを外します。ライフタイムを無効化して時間経過でエミッタの表示が消滅しないようにするためです。

エミッタの永続化についてはこの記事が参考になります。
UE4 NiagaraのLifetimeを無制限にする方法 - PaperSloth’s diary

UpdateMeshOrientationではメッシュのZ軸の回転を制御しています。NiagaraSystemにエミッタを追加した後で個別に回転を調整(回転の速度を変えたり、逆回転にしたり...)するので、スクショでは-0.3を指定していますが 実際は数値を入れなくても大丈夫です。

 

f:id:ten0313:20210611063721p:plain

レンダリングのタブの"SpriteRenderer"を削除して"MeshRendere"を追加します。
PartickeMeshには最初につくった平面のメッシュを設定します。
"OverrideMaterials"を有効化してさっき作ったマテリアルを設定します。

これでこのエミッタに関しては完成です。

f:id:ten0313:20210611064444p:plain

左回りするエミッタが作れているでしょうか

 

次にこのエミッタを作ります。さっき作ったものの、伸び縮みする版みたいな感じです。
エミッタの方はさっきのと共通ですが、伸ぼ縮みするマテリアルを作る必要があります。

f:id:ten0313:20210611065319p:plain

マテリアルのノードの概要です。円を作るところは、伸び縮みしないモノを作ったのとほぼ同じです(円の大きさを少し大きくしましたが)。

f:id:ten0313:20210611065701p:plain

ここで伸び縮みさせています。Timeの小数点以下を取りだし、sine波にかけて動きをなめらかにします。
出力された数値を角度に変換して円から一部の線を取りだしています

できたマテリアルからエミッタを作ります。

f:id:ten0313:20210611070032p:plain

さっき作ったエミッタを複製して作ります。

f:id:ten0313:20210611070129p:plain

マテリアルを変更しておきます。

この要領でもうひとつ作ります。

 回転する点線のマテリアルを作ります。

f:id:ten0313:20210611070830p:plain

ノードの概要です。

 

f:id:ten0313:20210611071034p:plain

放射の図を作ってそこに円状の図を掛けて点線上の円を作りました。

さっきと同じく

f:id:ten0313:20210611070032p:plain

作った既存のエミッタを複製して

f:id:ten0313:20210611071630p:plain

マテリアルをセットします。

これで今回使うエミッタ、主要な4つのうち3つができました(回転するモノです)。

次に文字を表示するマテリアルを利用したカウントアップしてくれるエミッタを作っていきます。

 

f:id:ten0313:20210611073728p:plain

使用するマテリアルです
この中の"DebugScalarValuesSegment" ノードなのですが、既存のノードを解像したものになっています。
マテリアル上で数値を確認する"DebugScalarValues"ノードを複製します。

f:id:ten0313:20210611074542p:plain

DebugScalarValuesの中身

使いたい数字反転させ 縦に配置したテクスチャを用意します。

f:id:ten0313:20210611074754p:plain
複製したマテリアルノードの中の"Composite"というコメント内のTextureSampleのTextureをさっきの画像のものに設定します

f:id:ten0313:20210611074911p:plain
マテリアル内に数値を表示させる方法を色々やったんですけど(実際ある程度上手くいってたんですけど)既存のをいじった方が楽だって気付いちゃいました。

f:id:ten0313:20210611075723p:plain

表示する内容を入力するNumberのピンにDynamicParameterのひとつ目のピンに繋ぎます(DynamicParameter側のピンを"Number"とかにしておきます)。
MaximumNumberOfDigitsは表示する小数点以下の桁数を入力しておきます。

文字を表示するエミッタを作ります。"Empty"を元に作成します。

f:id:ten0313:20210611080827p:plain
基本的にはさっきまで作ったエミッタと共通ですが、UpdateOrientationで回転を加えることはことはしません。
「パーティクル更新」のタブに

f:id:ten0313:20210611080932p:plain

"DynamicMaterialParameter"を追加します。描画した数字のパーティクルの数値を変更するためです。
直接数値をFloat型で指定してもいいと思いますし、僕はfloat from curveで目紛しく数値が変わるようにしました。

f:id:ten0313:20210611082241p:plain

マテリアルを数値を表現するマテリアルにしておきます。

NiagaraSystemを作成します。

f:id:ten0313:20210611082835p:plain
さっきまで作っていたエミッタを好きなだけ追加します。

 

f:id:ten0313:20210611082956p:plain基本的には追加するだけでいいのですが、InitializeParticleのPositionOffsetのZ軸をそれぞれ設定します。
要は高さを変えます。

f:id:ten0313:20210611083154p:plain

MeshScaleModeをUniformに設定、Scaleをそれぞれ設定します(エミッタのおおきさを変えます)。

f:id:ten0313:20210611083409p:plain

UpdateMeshOrientationのRotationVectorのZ軸を変更します(回転量を変えます)。負の数を指定する事で逆回転ができます。

これでNiagaraSystemの完成です。出来たパーティクルをレベルに配置してみてください。

f:id:ten0313:20210611083848p:plain

できていますか?

 

ポストプロセスで露出を少し上げることでもっと「映え」させることができます!

f:id:ten0313:20210611084014p:plain

 

なにかわかりにくい事があったり、間違いがあればTwitterのDMとかにおねがいします。


[ この記事はブログ投稿者の憶測や考えによりつくられています。

よって書いてある内容に誤りや言い間違いがあるかもしれません。もし修正したほうがいい場所や「こういった言い方のほうが”ソレっぽい”よ」などがありましたら後に記載してあります、リンク先のツイッターアカウントに教えてくださると嬉しいです:) ]

 

東京高速戦術@VRゲーム制作 (@kousoku_tactics) | Twitter

【UE4 .26】スケルタルメッシュのモーションに合わせてパーティクルを発生させる【Niagara】

 これを作ります。


スケルタルメッシュの形に合わせてパーティクルをスポーンさせる

www.youtube.com
ほぼコレの通りにしたんですけど、パーティクルの各種設定とか UnrealEngineのバージョン違いで詰まった所もあるのでそういう所も含めて全部書いていきます。

 

作成の流れとしては

  1. 指定したスケルタルメッシュの形にパーティクルをスポーンさせるNiagaraModuleScriptを作る
  2. 「パーティクルのスポーン」に作ったNiagaraModuleScriptを追加する
  3. メッシュをセットする

です。ところどころ詰まった箇所はあるんですけど、youtubeの解説が丁寧だったので楽にできました。

 

NiagaraModuleScriptを作っていきます。
持たせる役割としては「スケルタルメッシュの形にパーティクルをランダムにスポーンさせる」ってものです。

最初に「スクリプトの詳細」タブからModuleUsageBitmaskを写真の様にします。

f:id:ten0313:20210608201551p:plain

これってどこでこのScriptを使うかを指定するモノって認識なんですけど合ってますか?
とりあえず今回はスポーンの時に使用するので(「メッシュの形に沿ってスポーンさせる」って機能を作りたいので)、"ParticleSpawnScript"を指定しています。

 

f:id:ten0313:20210608201403p:plain

NiagaraScriptModuleの概要です

 ノードの方を説明していきます。

 

基本的にスクショの通り組んでいって貰えればいいんですけど、自分の使っている4.26バージョンでは左下の"GetRandomInfo"のノードが検索しても出てきませんでした。過去のバージョンでは存在するノードだったのですが 、いつのまにか表示されないようになっちゃってるみたいです

f:id:ten0313:20210608203120p:plain

検索しても出てこない...


エディタ内には存在しているようなので、表示されるように設定します。

f:id:ten0313:20210608203248p:plain

コンテンツブラウザ内の「Niagaraコンテンツ」内で「Get Random Info」を検索するとでてきます。

f:id:ten0313:20210608203427p:plain

「スクリプトの詳細」内の「LibraryVisiblity」を"Exposed"にセットして、コンパイルしてから適用させます。

f:id:ten0313:20210608203617p:plain

でました!

これで自分の作るModuleScript内でも"Get Random Info"が使えるようになりました。

ModuleScriptを作成する上で詰まるところはこれでもう無いと思います。

やってることの内容としては

f:id:ten0313:20210608204131p:plain

スケルタルメッシュをマップ取得で受けとって、"RandomTriangle"でポリゴンメッシュでメッシュ上のポリゴンをランダムで取得します。("RandomInfo"は乱数の生成に関する設定を扱かってるんだと思う)

 Calculates info needed by other RNG functions about seeds and determinism,

 "Get Random Info"ノードのDescriptionより

 

シードと決定論について他の RNG 関数が必要とする情報を計算します。

Google翻訳の結果


RNG関数ってのはRandomNumberGeneratorについての事であることから、RandomTriangleノードで扱う乱数の設定をしているんだと思いました。

 

f:id:ten0313:20210608205143p:plain


ModuleScriptの後半です。

"RandomTriangle"で取得したポリゴンメッシュの情報を"Get Skinned Triangle WS"でワールド基準のものに変換します(ノード名の"WS"とは"WorldSpace"の略です)

その中の"Position"のピンをひっぱって"Map Set"のパーティクルの位置を指定する"Position"に繋ぎます。

 

これでパーティクルの位置がメッシュの形にセットされるようになります。
"NMS_SetPositionSkeletalMesh"って名前で保存します。

 

NiagaraSystemを作成して設定をいじっていきます。

f:id:ten0313:20210608211438p:plain

Emitterも含めての概要です。「パーティクルのスポーン」にさっき作ったModuleScriptを追加しています。

 

"Empty"を元にエミッタを追加します。

f:id:ten0313:20210608212107p:plain

基本的に これで追加したエミッタそのままで、いくつかモジュールを追加していったのでそれらを説明します。

f:id:ten0313:20210608212317p:plain

「エミッタの更新」に"Spawn Rate"を追加しました。ベースとなるスケルタルメッシュがモーションさせている間も連続してパーティクルに出てきてもらいたいので設定しました。"SpawnRate"は100000にしました。正直ここまで要らないと思うんですけど、ゲームに組みこむわけでもないし、多い方がSNS映えするかな~って魂胆です。

 

f:id:ten0313:20210608213248p:plain

「パーティクルのスポーン」の"Initialize Particle"です。ライフタイムを短かくして、スプライトのサイズを小さくしています("Sprite Size Mode"を"Random Uniform"にしている部分です)

 

f:id:ten0313:20210608213441p:plain

NMS Set Particle Position

さっき作ったモジュールです。今回はグレイマンにモーションを付けてパーティクルをつけようと思っているので、"SK_Mannequin"を指定しました。

 

f:id:ten0313:20210608213602p:plain

Color

男の子なので青くしました

 

f:id:ten0313:20210608213639p:plain

GravityForce

「パーティクル更新」の欄です。重力を適用させました。

 

f:id:ten0313:20210608213735p:plain

Scale Sprite Size

スプライトのサイズをスポーン後、徐々に小さくするようにしました。今回はスプライトのライフタイムが比較的短いので、地面に達する前に徐々に消滅するようにしました。

 

これでNiagaraSystemは完成です。"NS_BurstMesh"って名前で保存しました。

 

次に踊らせるグレイマンの方でNiagaraパーティクルをセットしていきます。

 

UnrealEngineのに用意されているThirdPersonテンプレート内の"ThirdPersonCharactor"のイベントグラフに↓を追加します。

f:id:ten0313:20210608214406p:plain

これでパーティクルをセットします。

これで大体は完成なのですが、このままではグレイマン自身のメッシュが見えてしまっています。パーティクルのスポーンでグレイマンの形を表現したいので、グレイマンのマテリアルに透明なのを適用させます

f:id:ten0313:20210608221008p:plain

透明マテリアル

メッシュのvisibleとかHidden in Gameをオンオフにしたらいいのかなって最初は思ってたんですけど、それをするとパーティクルがメッシュのモーションに追従してスポーンしてくれないのでこの方法をとりました。もっと良い方法が探せばあると思います。

 

これでグレイマンのメッシュに沿ってパーティクルが発生するようになっています。

 

こんな感じです。

 

ダンスを踊らせると

 こんな感じになったでしょうか。

なにかわかりにくい事があったり、間違いがあればTwitterのDMとかにおねがいします。


[ この記事はブログ投稿者の憶測や考えによりつくられています。

よって書いてある内容に誤りや言い間違いがあるかもしれません。もし修正したほうがいい場所や「こういった言い方のほうが”ソレっぽい”よ」などがありましたら後に記載してあります、リンク先のツイッターアカウントに教えてくださると嬉しいです:) ]

 

twitter.com

 

f:id:ten0313:20210608221738p:plain

Â