ナレッジ

Day 2: 最小エミッタと Emitter State

最小エミッタ(Minimal)を開いて、UE が「これが無いと動かない」と考えた 4 つのモジュールと、その先頭にいる Emitter State の中身を見ていきます。

UE 5.7 の Fountain テンプレート(FountainLightweight)を黒地で動かし、暖色に光る粒が下から吹き上がるアニメーション。左に「Niagara 100日 Day 2 いちばん小さいエミッタの中身」の文字

Day 1 では Fountain(噴水)のテンプレートから System(システム) を作って、入れ子とスタックを眺めました。

ただ、テンプレートって、最初からモジュールがある程度入っています。 全部載った状態から入ると、どれが「無いと動かないもの」で、どれが「噴水らしく見せるための飾り」なのか、区別がつきにくいです。なので今日は、UE 自身が「これだけは要る」と考えた、いちばん小さいエミッタ を開いてみましょう。

そのいちばん小さいエミッタに入っているのは、4 つのモジュールだけです。今日はその 4 つを見ていって、先頭にいる Emitter State(エミッタステート) で、エミッタの寿命(何秒出して、何回くり返すか)がどこで決まっているのかを確かめます。

1. まずは最小単位のエミッタを作ってみましょう

System(システム) のグラフ上で右クリックすると、エミッタを足すメニューが 3 つ出てきます。

System のグラフを右クリックしたメニュー。上から「エミッタを追加...」「最小エミッタを追加」「軽量エミッタの追加」の 3 つに赤枠と番号 ①②③
  • ① エミッタを追加…(E) … テンプレートから選ぶ、いつものやつ
  • ② 最小エミッタを追加 … 動くのに必要な分だけが入ったエミッタ
  • ③ 軽量エミッタの追加 … 名前は似ていますが、これだけ少し毛色が違います

3 つ目の軽量エミッタは、記事の後半で寄り道して見ます。 では、2 つ目の最小エミッタは実際どのくらい薄いのか。Fountain(ファウンテン) と並べてみます。

2. 最小エミッタと Fountain を比べてみましょう

Fountain(ファウンテン) と、最小エミッタ(Minimal)を横に置いてみます。

Fountain と最小エミッタ(Minimal)のスタックを左右に並べた画面。Fountain は 11 個のモジュールが積まれ、Minimal は 4 個だけ。どちらも右上は CPU

Fountain のほうは、Shape Location(形状の位置)・Add Velocity(速度を追加)・Gravity Force(重力)・Drag(抗力)・Scale Color(カラーをスケール)……と、噴水らしく見せるためのモジュールがずらっと積んであります。 ちなみに Fountain の Emitter State には、最初から Self のバッジが付いています(Self の話は 4 章で出てきます)。

最小エミッタのほうも、Fountain と同じ構造です。 余談ですが、エンジンの中を覗いてみると、テンプレートのフォルダに Fountain と Minimal(ミニマル) がとなり同士で並んでいて、「最小エミッタを追加」は、その Minimal を読み込んでいるだけでした。 つまり種類としては Fountain とまったく同じもので、載っているモジュールが少ないだけです。

その最小エミッタのスタックを開くと、こうなっています。

最小エミッタ(Minimal)のスタック。エミッタのスポーンの段は空で、Emitter State・Initialize Particle・Particle State・Sprite Renderer の 4 行に赤枠と番号 ①〜④

たったこれだけでした。

段入っているモジュール
① エミッタの更新Emitter State(エミッタステート)
② パーティクルのスポーンInitialize Particle(イニシャライズパーティクル)
③ パーティクル更新Particle State(パーティクルステート)
④ レンダリングSprite Renderer(スプライトレンダラー)

4 段に 1 つずつ。これでもちゃんと動きます。 段の名前だけなら、いちばん上に「エミッタのスポーン」もあって全部で 5 段です。ただ、最小エミッタではこの段が空っぽなので、表には入れていません(5 章で段の数を比べるときは、この空の段も 1 段に数えています)。 そして、その先頭に入っているのが Emitter State。今日見ていくモジュールです。

3. Emitter State を開いて中身を確認

最小構成に残っているくらいなので、さぞ設定がぎっしり入っているんだろうと思うかもです。エミッタの更新の先頭にある Emitter State(エミッタステート) をクリックして、詳細で見てみます。

左のスタックで Emitter State を選ぶと、右の詳細パネルに Life Cycle Mode と Scalability Mode の 2 行だけが出ている画面

Emitter State の行の右に、System(システム) のバッジが付いています。

詳細に出てくるのは、区分の見出しを含めて 4 行だけでした。区分は Life Cycle(ライフサイクル) と Scalability(負荷に応じて品質を上げ下げする仕組み)の 2 つです。

Emitter State の詳細パネル。タブは「すべて」が選ばれていて、Life Cycle Mode と Scalability Mode のどちらも System と Self の二択で、System が選ばれている
区分項目選べるもの
Life CycleLife Cycle Mode(ライフサイクルモード)System / Self(セルフ)
Scalability(スケーラビリティ)Scalability Mode(スケーラビリティモード)System / Self

設定は 2 つ。以上です。

タブが「すべて」になっているのに、これだけなんです。エミッタの一生を決めるモジュールなのに、寿命そのものの数字がどこにもありません。

3-1. System と Self の違いを見ていきます

2 つとも、選ぶのは System か Self かの二択です。

  • System … 寿命の計算を、親の System にまかせる
  • Self … このエミッタが自分で持つ

最小エミッタは、両方とも既定で System になっていました。 System は、グラフの一番上にある、青緑の帯に名前(NewNiagaraSystem1)が書かれた箱のことです(System の中身は、また違う日に解説します)。

グラフの一番上にある System の箱。青緑の帯に NewNiagaraSystem1 と名前が書かれ、システム更新の段に System State が 1 つ入っている

System の側にも、「システム更新」の段に System State(システムステート) が入っています。

エミッタの寿命は、エミッタが持っているとは限らないです。 既定では親に預けているので、Emitter State の中には、預け先を選ぶスイッチが 2 つあるだけ、という状態でした。 「エミッタの状態を決めるモジュール」という名前から、勝手に「ここに秒数とか回数とかが並んでいるんだろう」と考えるのが普通だと思うのですが、開いてみると並んでいないので、少し困ります。

そして UE の公式説明には、こう書いてあります。

親の System にライフサイクルを計算させて子の Emitter(エミッタ) に渡すほうが、たいていの場合、かなりの最適化になります

つまり、預けたままのほうが速いです。あくまでケースバイケースで調整してください。基本は System のまま、「このエミッタだけ違うタイミングで動かしたい」というはっきりした理由が出てきたときに、はじめて Self にする。その順番がよさそうです。

といっても、最初は気にせずにバシバシ変更しても大丈夫です。

4. Life Cycle Mode を Self に切り替えて、増える行を確認

では、Self(セルフ) にしたら何が出てくるのか。切り替えてみました。

Life Cycle Mode を System から Self に切り替えると、その下に Inactive Response・Loop Behavior・Loop Duration などの行が増えるアニメーション

Life Cycle Mode(ライフサイクルモード) を Self にすると、すぐにその下に行がぶわっと増えます。Scalability(スケーラビリティ) のほうはまだ System(システム) なので、こちらは 1 行のままです。

出てきた項目中身
Inactive Response(インアクティブレスポンス)止められたときの後始末をどうするか。3 つから選びます
Loop Behavior(ループビヘイビア)Infinite(インフィニット) / Once(ワンス) / Multiple(マルチプル) の 3 択
Loop Duration(ループデュレーション)ループ 1 回の長さ(既定は 1.0 秒)
Recalculate Duration Each Loop(リカルキュレート デュレーション イーチ ループ)ループのたびに長さを計算し直すか
Loop Delay(ループディレイ)待ち時間を入れるか(チェックを入れると使えるようになります)

Inactive Response を開くと、こんな 3 つが出てきます。

Inactive Response のプルダウンを開いた画面。Complete・Kill・Continue の 3 つが英語の説明つきで並んでいる
選ぶもの何が起きるか
Complete(既定)いま出ている粒を最後まで見せてから、エミッタを終わらせます
Kill(キル)エミッタも粒も、その場で即座に消します
Continue(コンティニュー)エミッタは止まりますが、System が終わるまでは死なずに残ります

止め方だけで 3 通りあります。粒を途中で消すか、最後まで見せるかで、見え方はずいぶん変わりそうです。

探していた「秒数」と「回数」は、無かったのではなくて、System に預けているあいだは出す必要がないので、たたまれていただけでした。Emitter State(エミッタステート) は、既定では中身が全部たたまれているモジュールです。

4-1. Loop Behavior も切り替えてみます

Loop Behavior は 3 択なのですが、選んだものによって、その下に並ぶ行そのものが入れ替わります。

選んだものその下に出てくるもの
Infinite(既定)Loop Duration / Recalculate Duration Each Loop
OnceLoop Duration Mode(Fixed / Infinite)が増えて、Recalculate Duration Each Loop のほうは消えます
MultipleLoop Count(何回まわすか)が増えます

Infinite → Once → Multiple の順に切り替えると、こうなります。

Loop Behavior を Infinite・Once・Multiple の順に切り替えると、その下の行が入れ替わるアニメーション。Once で Loop Duration Mode が増え、Multiple で Loop Count が出る

Once では Loop Duration Mode(ループデュレーションモード) が増えて、Recalculate Duration Each Loop が消えています。 Multiple では、代わりに Loop Count(ループカウント、何回まわすか)が出てきます。

Loop Delay にチェックを入れると、さらに Delay First Loop Only(最初の 1 回だけ待たせる)が出てきます。

Loop Delay にチェックを入れた画面。すぐ下に Delay First Loop Only の行が 1 つ増えている

チェックを入れるたびに 1 行増える、という作りです。

4-2. Scalability Mode も Self にしてみます

Scalability Mode(スケーラビリティモード) のほうも同じで、Self にすると、下に 3 行増えます。

  • Enable Distance Culling(イネーブル ディスタンス カリング) … 遠いときに切る
  • Enable Visibility Culling(イネーブル ビジビリティ カリング) … 見えていないときに切る
  • Reset Age On Awaken(リセット エイジ オン アウェイクン) … 起き直すときに歳を戻すか
Scalability Mode を Self に切り替えると、Enable Distance Culling・Enable Visibility Culling・Reset Age On Awaken の 3 行が増えるアニメーション

そして、この 3 つにチェックを入れると、それぞれの下がまた増えます。Distance Culling(ディスタンスカリング) を入れると距離の数字と Spawn Count Scale(スポーン カウント スケール) が出てきて、しまいにはカーブのエディタまで開きました。

Scalability の 3 つにチェックを入れた画面。距離の数字、Spawn Count Scale、カーブのエディタまで開き、詳細パネルが縦に長く伸びている

最初に開いたときは 2 行だったので、同じモジュールとは思えません。

ここまでが最小エミッタの話です。最後に、メニューの 3 つ目にあった軽量エミッタに寄り道します。

5. 最小エミッタと軽量エミッタを比べてみましょう

メニューに上から並んでいるので、普通だと「エミッタを追加、最小、軽量」の順に、だんだん中身を削っていくものっぽく見えるのですが、実はそんな感じではないです。

軽量エミッタにカーソルを合わせると、説明が出ます。

モジュールもレンダラもない軽量エミッタが追加されます

右クリックメニューの「軽量エミッタの追加」にカーソルを合わせ、「モジュールもレンダラもない軽量エミッタが追加されます」と説明が出ている画面

説明だけ読むと、モジュールもレンダラも無い、ただの空箱です。 ただ実際には、最低限のエミッタがあります。

左のビューアに白い丸が 1 つだけ出ていて、右のグラフに Empty という名前の軽量エミッタが置かれている画面。右上のバッジは LW

スポーン・シミュレート・レンダリングに最低限のモジュールだけが入っていて、UE5 の Niagara(ナイアガラ) のビューアには小さい白い丸が 1 つ出ます。

軽量エミッタは、最小エミッタとはそもそも種類が違います。いちばん分かりやすいのがエミッタの右上のバッジで、ふつうのエミッタなら CPU(または GPU)と出る場所に、LW(Lightweight=軽量の略)と出ます。

軽量エミッタのスタック。右上のバッジが LW で、段はスポーン・シミュレート・レンダリングの 3 つだけ

同じ場所に出るということは、CPU でも GPU でもない、3 つ目の走らせ方ということだと思います。別の走り方をする、別のエミッタという感じです。

段の数も変わります。

ふつうのエミッタ(Fountain・最小エミッタ)軽量エミッタ
バッジCPU / GPULW(エルダブリュー)
段の数5 段(最小エミッタは、エミッタのスポーンが空)3 段
段の名前エミッタのスポーン / エミッタの更新 / パーティクルのスポーン / パーティクル更新 / レンダリングスポーン / シミュレート / レンダリング
足せるモジュール自分で作ったものも足せるエンジンが用意した分から選ぶ

並べて描くと、こういう関係です。

図:左にふつうのエミッタ(5 段)、右に軽量エミッタ(3 段)を並べ、同じ働きのモジュールどうしを線でつないだ比較

「エミッタのスポーン」と「エミッタの更新」の 2 段がまるごと消えて、代わりに「シミュレート」が 1 つ。エミッタの一生を扱う段が無いので、今日見てきた Emitter State(エミッタステート) も、スタックのどこにも居ません。

寿命の設定は、置き場所が別になっているんだと思います(ここはまだ開いて確かめていません)。今日の話でいうと、軽量エミッタは、寿命を System(システム) に預けるかどうかを選ぶ前に、そのスイッチを置く場所が無い、という状態です。

表示が英語の行と日本語の行で混ざっていることに気づいたかもしれません。その理由は下の Tips にまとめました。本筋とは別の話なので、読み飛ばしても大丈夫です。

Tips(読み飛ばして OK)|日本語と英語が混ざる理由

やっていることは同じなのに、ふつうのエミッタでは Spawn Burst Instantaneous・Initialize Particle・Solve Forces and Velocity と英語で出て、軽量エミッタでは「スポーン瞬間バースト」「パーティクルを初期化」「力と速度を解決」と日本語で出ます。

理由は、モジュールの置き場所の違いでした。ふつうのエミッタのモジュールはエンジンの中のファイルで、スタックに出ているのはファイル名です。ファイル名は翻訳されないので、日本語版でも英語のままです。軽量エミッタのモジュールはエンジンのプログラムの中に直接書かれていて、表示名が翻訳の対象になるので日本語で出ます。Sprite Renderer だけ両方英語なのは、日本語の訳がまだ用意されていないからです。

実用の話を 1 つだけ。検索するときは英語名のほうが早いです。「力と速度を解決」より Solve Forces and Velocity で調べましょう。この連載で英語を併記しているのは、そのためです。

6. 今日の一歩 — 最小エミッタを 1 つ、足してみる

言葉だけだとピンと来ないので、実際に触ってみましょう!

  1. Day 1 で作った System(システム) を開く
  2. グラフの何もない所で 右クリック して、最小エミッタを追加 を選ぶ
  3. 足されたエミッタ(Minimal)の エミッタの更新 にある Emitter State(エミッタステート) をクリック
  4. 右の詳細で、Life Cycle Mode(ライフサイクルモード) と Scalability Mode(スケーラビリティモード) の 2 つだけが出ることを見る
  5. 隣に Fountain(ファウンテン) も置いて、同じ「エミッタ」なのに中身の量が全然違うのを並べて眺める
  6. 余力があれば、Life Cycle Mode を Self(セルフ) にして、下に行が増えるのを見る。さらに Loop Behavior(ループビヘイビア) を Once(ワンス) や Multiple(マルチプル) に切り替えて、その下がまた入れ替わるのを見る
図:今日の一歩の 6 つの手順。①System を開く ②右クリックで最小エミッタを追加 ③Emitter State をクリック ④詳細に出るのは 2 つだけ ⑤Fountain と並べる ⑥Self に切り替える

4 と 5 だけで今日は十分です。「エミッタって、実はこんなに薄くても動くんだ」が体で分かると、これから 100 日かけて積んでいくモジュールが、全部あとから足された飾りなんだと見えてきます。

7. ここでつまずいたら、だいたいこの 3 つです

  • 最小エミッタを足したのに、画面に何も出ない … 最小エミッタは粒を動かすモジュールが入っていないので、その場にぽつぽつ出るだけです。派手なものは出ません(壊れていません)。
  • Emitter State(エミッタステート) をクリックしても 2 つしか出ない … それで合っています。今日の記事はまさにその話です。
  • 軽量エミッタを足したら、名前が「Empty(エンプティ)」で出てきた … 空っぽという意味ではなくて、エンジンがいったん空のエミッタを作ってから軽量に切り替える作りになっているので、そのときの名前がそのまま残っているだけです。気にしなくて大丈夫です。

8. 読み方メモ(この回に出てきた英語)

  • Emitter State(エミッタステート)… エミッタの状態を決めるモジュール
  • Minimal(ミニマル)… 最小の
  • Life Cycle(ライフサイクル)… 生まれてから終わるまでの一生
  • Mode(モード)… やり方の切り替え
  • Scalability(スケーラビリティ)… 負荷に応じて品質を上げ下げする仕組み
  • Initialize(イニシャライズ)… 初期化する
  • Particle State(パーティクルステート)… 粒の状態を管理するモジュール
  • Sprite Renderer(スプライトレンダラー)… 粒を板の絵として描く担当
  • Loop(ループ)… くり返し。Infinite(インフィニット)は無限、Once(ワンス)は 1 回だけ、Multiple(マルチプル)は複数回
  • Loop Duration(ループデュレーション)… くり返し 1 回の長さ
  • Loop Delay(ループディレイ)… くり返しの前に入れる待ち時間
  • Inactive Response(インアクティブレスポンス)… 止められたときにどうするか
  • Culling(カリング)… 負荷を下げるために、描くのをやめること
  • Lightweight(ライトウェイト)… 軽量。エミッタの右上に出る LW はこれの略です
  • Solve Forces and Velocity(ソルブ フォーシズ アンド ベロシティ)… 力と速度を解決する。日本語版では「力と速度を解決」と出ます
  • Spawn Burst Instantaneous(スポーン バースト インスタンテニアス)… 一瞬でまとめて生む。日本語版では「スポーン瞬間バースト」と出ます

今日はたくさんですね。

9. まとめ

今日わかったことは 3 つです。

  1. 最小エミッタに入っているモジュールは 4 つだけです。Emitter State(エミッタステート)・Initialize Particle(イニシャライズパーティクル)・Particle State(パーティクルステート)・Sprite Renderer(スプライトレンダラー)。
  2. Emitter State の設定は、Life Cycle Mode(ライフサイクルモード) と Scalability Mode(スケーラビリティモード) の 2 つだけです。どちらも System(親にまかせる)か Self(自分で持つ)かを選びます。Self(セルフ) にすると、ループの長さや回数の設定が出てきます。
  3. 軽量エミッタは、最小エミッタをさらに削ったものではなく、別の種類のエミッタです。段が 3 つしかなく、Emitter State もありません。
図:Day 2 のまとめ 3 つ。最小エミッタは 4 つだけ/Emitter State のスイッチは 2 つ/軽量エミッタは別の種類

出てきた設定が実際にどう効くかは、まだ動かして確かめていません。次回、ひとつずつ動かしてみます。

今日は「開けてみたら、思っていたのと違った」という回でした。最小エミッタの薄さが見えていると、テンプレートを読むのがぐっと楽になります。同じところで一度きょとんとした方に、ちょっとでも役に立てば幸いです。