ゲームエフェクトデザイナーのブログ | A Real-Time VFX Artist's Blog

About Making Materials on UE, Making Tools with C#, etc

C#で正規表現による置換を行う

C# で最初に作ったツールは「特定のリストを作って専用のフォーマットに整形した上でテキストデータで出力するもの」という感じでしたが、そこで躓いた部分は正規表現による置換でした。

その置換についてメモしておきたいと思って用意したのが下図のツールです。

f:id:moko_03_25:20170807211406j:plain

ここでいきなりUE4の話になりますが、UE4のアセット管理ツールであるコンテンツブラウザ上でアセットを右クリック「リファレンスをコピー」を選択すると、クリップボードにアセットの情報がコピーされます。

f:id:moko_03_25:20170807211352j:plain

それは以下のような書式です。

アセットの種類 + ' + アセットのフルパス + . + アセット名 + '


で、例えばあるアセットの場所をメールでお知らせするような時には、フルパスの前後の文字列が邪魔だったりします。それを正規表現の置換で除去するのが今回のツールです。

ちなみに余談ですが、コンテンツブラウザ上でアセットを選択して Ctrl + C でリファレンスをコピーできることを最近同僚に教えてもらいました。
知りませんでした。。これは便利!

f:id:moko_03_25:20170807211403j:plain

そしてアセットのリファレンス情報をツールの上段のテキストボックス内にペーストします。
すると下図のように貼り付けられました。
先に書いた通り、メールに記載したりするには余計な情報がごちゃっと付いています。

f:id:moko_03_25:20170807211400j:plain

次に「パスから余計な情報を除去」ボタンを押すと、下段のテキストボックスに置換された結果が表示されます。

あとはオマケで「クリップボードへコピー」ボタンと「クリア」ボタンも追加しました。

f:id:moko_03_25:20170807211349j:plain

実装したもの


さて、ここで実装した内容は以下になります。

・テキストボックス内で Ctrl + A を入力すると文字列を全選択する
・「クリア」ボタンでテキストボックス内の文字列を全消去する
・「クリップボードへコピー」ボタンで文字列をクリップボードにコピーする
・「パスから余計な情報を除去」ボタンでリファレンス情報を単なるフルパス情報に整形する

1つずつ見ていきます。

テキストボックス内での文字列の全選択


ツールを作ってみて初めて気付いたのですが、普段はテキスト入力できるパネル内で当たり前のように可能な全選択ショートカットですが、これは実装しないと可能になりません。

実装は簡単で、テキストボックスの KeyDown イベントに下記の2行を追記するだけです。
青文字部分はテキストボックスのNameプロパティで設定した名前です)

//Ctrl + A で全選択可能にする
private void textBoxInput_KeyDown(object sender, KeyEventArgs e)
{
    if (e.Control && e.KeyCode == Keys.A)
    textBoxInput.SelectAll();
}

 

文字列のクリアとクリップボードへのコピー


これらも実装は簡単で、ボタンのクリックイベントそれぞれに下記1行を追加するだけです。
青文字部分はテキストボックスのNameプロパティで設定した名前です)

//「クリア」ボタンでtextBoxの内容を消去
private void buttonInputClear_Click(object sender, EventArgs e)
{
    textBoxInput.ResetText();
}
//「クリップボードへコピーする」ボタンの挙動
private void buttonResultCopy_Click(object sender, EventArgs e)
{
    Clipboard.SetText(textBoxResult.Text);
}
//「クリア」ボタンでtextBoxの内容を消去
private void buttonResultClear_Click(object sender, EventArgs e)
{
    textBoxResult.ResetText();
}

 

正規表現による置換


問題はここからです。

正規表現の置換には「RegularExpressions」を利用しました。
LINQを使うとか色々方法があるっぽいのですが、よく検索で出てくるこちらを試しました。

まずは Form1.cs の先頭に下記の1行を追加します。

using System.Text.RegularExpressions;


次にボタンクリックイベントでの置換の内容です。

//「パスから余計な情報を除去」ボタンの挙動
private void buttonReplace_Click(object sender, EventArgs e)
{
    //一時的に文字列を扱うための変数
    string st = textBoxInput.Text;

    //先頭の余分な情報を置換でカット
    st = Regex.Replace(
        st,
        "^[^/]+'", //行頭から連続するスラッシュ以外の文字列
        "", //空に置換(文末以外の空白行も削除される)
        RegexOptions.Multiline); //改行記号も1つの文末として処理する
    //末尾の余分な情報を置換でカット
    st = Regex.Replace(
        st,
        "[.][^/]+'", //行末まで連続した.で始まるスラッシュ以外の文字列
        "", //空に置換
        RegexOptions.Multiline); //改行記号も1つの文末として処理する
    //文末の空行を削除
    st = Regex.Replace(
        st,
        "[\r\n]*$", //文末で0回以上繰り返す改行
        "\r\n"); //改行1つだけに置換

    textBoxResult.AppendText(st);
}


文字列を改行部分で分割して配列に代入し、for文で1行ずつ置換していく‥といったような面倒なことをしなくても、改行を含んだ文字列に対して「Multiline(複数行)」オプションを指定してそのまま置換するだけでいけました。

3度の 置換によって

 ・行頭の情報の除去(文末以外の空行も同時に除去)
 ・行末の情報の除去
 ・文末に空行が複数ある場合に1行だけにする

‥を行っています。

正規表現のルールはこちらの記事を参考にさせて頂きました。

正規表現の基本: .NET Tips: C#, VB.NET


正規表現の厄介なところは、文字列の指定が記号だらけになって内容も結果も分かり辛く、なぜ置換がうまくいかないかも判断し辛いところですね。。

ただ、上記の置換のコード先頭でブレークポイントを設定して、変数 st をウォッチリストに追加して、1つの処理を順に進めて(ステップ実行して)いくと、変数 st の内容がどう変わっていくかをチェックすることができます。
(このあたりは1つ前に投稿した記事で紹介した書籍でも丁寧に解説されています)

例えばピリオド(\n以外の任意の文字列)を使って .+ で置換するとキャリッジリターンまで置換対象になって改行文字の「\r\n」が「\n」だけになってしまい、テキスト出力すると謎の連続改行が入ってしまうといったことが起こり、原因究明にしばらく手間取りましたが、ステップ実行して変数の中身を調べると原因がすぐに分かりました。

行末の情報を除去するための対象文字列に、行末を表す $ を使用していないのはそのためで、$ を使うと「.+」によって「\r」が削られてしまいました。
ここでは Path.GetFileName のようなメソッドで親フォルダパスを取得する方法は使わずあくまで置換でやりたかったので対処療法な感じになりましたが、どこかのタイミングで本職の方にちゃんとした指定方法を教えてもらおうと思っています。。

ウォッチリストの変数 st の状態。最初は空っぽ(null)

f:id:moko_03_25:20170807220954j:plain

▼ステップ実行でテキストボックスの内容が代入された様子("\r\n"が改行を表す部分)

f:id:moko_03_25:20170807220950j:plain

▼行頭の余計な情報が除去された(文末以外の空行も一緒に除去)

f:id:moko_03_25:20170807220947j:plain

▼行末の余計な情報が除去された

f:id:moko_03_25:20170807220944j:plain


ちなみに、置換結果の文字列はテキストボックスの中へ書き換えるのではなく「AppendText」を使って追記する形にしています。
すでに別の置換結果の文字列が存在する場合に新しい行へ追記したいと思ったからです。

そのためには、置換の最後には必ず1回分の改行を行って終わるように記述しています。

プロジェクトデータと実行ファイル


Googleドライブにアップしました。

MyTool_UE4PassReplace.zip - Google ドライブ

binフォルダの中にexeが入っています。

 

2017.11.18追記

 

C#のはじめ方

CGアーティストだってWindows用ツールを作りたい!

ということで C# を少しばかり触って簡単なツールをいくつか作ってみました。
思っていたよりもずっと敷居は低かったので、備忘録がてら軽くまとめておこうと思います。

※プログラム自体の初心者が書くアーティスト向けの記事です

基本的な文法の習得


とは言え最低限の文法をまずは覚える必要があります。
「何か作りたい!」のに作れない、この第一歩が最初のもどかしい時間とは思いますが、どうしてもここは頑張るしかないところだと思います。

さて、どんなプログラミング言語でも大体同じなのかなと思いますが、最初に覚える必要がある要素は以下のあたりと思います。

 変数の宣言・代入・型
 メソッド・引数・戻り値
 if文による条件分岐
 配列とfor文による繰り返し
 クラス・オブジェクトの生成
 using(pythonで言うところのimport)
 アクセス修飾子(publicとか)

とりあえずここまで覚えれば、クラスの継承とかコンストラクタとかオーバーロードといったクラス周りのややこしいルールの学習は後回しで良いと思います。
ほんのちょっとしたツールだとクラスを自作しなくても大丈夫な感じですし、実装したいことは工程ごとにGoogleで調べてコピペで大体いけます。

ではどうやって覚えるかというと、自分の場合はこちらのシリーズにお世話になりました。
(正確に言えば同じ投稿者の方のJava超入門シリーズでまずはJavaから覚えました。JavaC#と文法がかなり近いです)

メモ帳でC#超入門 #1 環境構築 by T.Umezawa - ニコニコ動画

この方の動画はとても丁寧で分かりやすく解説されていて、以下のあたりが特徴です。

・声が聞きとりやすい
・メモ帳でコーディングしてコマンドプロンプトコンパイルするスタイル
RPGゲームを作っていきながらの解説
・エラーが出て修正する手順を丁寧に繰り返して解説
・煩雑になったコードを修正対応しやすい&読みやすいコードにどう整形していくかを丁寧に解説
・ドキュメントの調べ方を解説


‥という感じで、単に文法の説明で終わらずとてもポイント高いと感じます。

また、いきなり本を買って手元でページをめくりながら試すよりも、動画を流しながら試す方が初心者にも入りやすくてとても良いですね!

いやいや、メモ帳とかコマンドプロンプトじゃなくて最初からIDE(開発環境)でやりたい!
手っ取り早く文法だけ知りたい!

‥という方にはこちらのシリーズがおすすめです。

【プログラミング講座】第1回 プログラム言語の種類【独り言】

こちらの動画の良いところは以下のあたりです。

Visual Studioを使ったスタイル
・WindowsFormでのツールを制作していきながらの解説
・若干ゲームを作るパートもある
・WindowsFormの各コントロール(ウインドウを構成するパーツ)の解説が充実している


どうすればウインドウサイズを変えても崩れないレイアウトを作成できるのかというあたりの解説も含まれていて、これが案外ググっても出てこないため個人的にとてもポイント高いと思いました。

そうして基本的なところが一通り馴染んだら、次のステップに移って良いと思います。

逆に、上に挙げたあたりは最初に覚えておかないと、入門書を買って読んでもついていけない可能性がありますし、やりたいことをネットで検索してサンプルコードを見つけてもそのままでは動かない時に、自力では対応することができなくて詰んでしまいます。。

実際に何かツールを作ってみる


早速色々作りたいところですが、自分の場合はこちらの書籍を購入して進めました。

作って覚えるVisual C# 2017 デスクトップアプリ入門

作って覚えるVisual C# 2017 デスクトップアプリ入門

 

色んなツールを作りながらステップアップしていける、とても良い本でおすすめです!

C#で具体的なツールを実際に作ってみよう的な本って思いのほか少ないんですね。
多くの書籍が文法の解説や逆引きだったりします。

こちらの書籍は Visual Studio Community 2017 を導入して、.NET向けAPI(?)の「Windowsフォームアプリケーション」というWindowsでお馴染なGUIのツールをC#で作っていく内容になっています。

Visual Studioというと、本格的なプログラミング環境でとても大層でハードル高いイメージがありましたが、むしろ初心者に優しい機能がてんこ盛りなんですね。

何といってもWindows向けのツールのGUIを、ボタンやテキストボックスなどペタペタ貼り付けるだけでほとんどコーディングせず作れてしまいます。

また、変数や関数などに色が付いたり(シンタックスハイライト)、コンパイル時にエラーが出る部分がリアルタイムで表示されたり、定義済みの変数や関数が予測変換でリストアップされたりと便利すぎます。

1命令ずつ順に実行(ステップ実行)してその時々の変数の値を確認しながらデバッグできたりといったあたりも大変便利。。

ただこちらの書籍、最初は簡単なツールから始まって色んなツールを順番に作っていくのですが、最後の家計簿ツールで難易度が急に上がって感じました。。

家計簿ツールの途中でどこを間違ったのか動かなくなってしまい、手順を追っていっても何をしているのか理解できなくなってきていたため、いったん書籍は中断して、好きなものを作っていくステップに移りました(家計簿ツールは一年後に再挑戦してみたらちゃんと完成しました!)。

結果的にもそれで良かったです。

書籍を最後までやらずともツールを作る手順は大体学べます。
あとはネットで調べつつ色々作ってみるべし!という感じでしょうかっ。

ツールを作っていく過程で、クラスをnewしなくても直接使えるものがあったり、見つけたサンプルコードで使われている型が int や string ではなく「var」であったり、触っている上で色々と「?」に遭遇しますが、そういうのは気になったタイミングで調べて、よく分からなければ後回し‥で良いと思います。


という訳で、まずは基礎文法を勉強して上記書籍を一通り試してみるという感じでツール作りに入っていきました。ここまでで、休日などがっつりと費やして一気に進めたら 3週間ほどという感じでした。

その後さらに2週間ほどでほんのちょっとした小さなツール(テキストボックスに入力したファイルパスからファイル名の部分を削るだけのツールとか)を6つ7つ作ってみたらツール作りにも徐々に慣れてきて、今後も徐々にステップアップしながら色々と作っていける手応えを感じました。

楽しくてお仕事にも役に立つので、CGアーティストな皆さまもぜひぜひC#でツールを作ってみてみてください!

エクセルで条件付き書式を適用したのち書式を残してクリアする方法

エクセルの備忘録。

下図のようなリストで、B列の値が一定の値以上ならその行の書式を変えたいといったような場合には「条件付き書式」機能を使うと便利です。

f:id:moko_03_25:20160831022607p:plain

まず書式を反映させたい列、または範囲を選択しておきます。

f:id:moko_03_25:20160831022608p:plain

ホームタブにある「条件付き書式」の「新しいルール」を選択。

f:id:moko_03_25:20160831022609p:plain

数式を使用して、書式設定するセルを決定」を選択し、下図のように計算式を記述した後に「書式」ボタンを押して自由に書式を設定します。

=$B1>=80

この図の場合は「B列に対してB1のセル以降の値が80以上なら赤文字にする」です。

f:id:moko_03_25:20160831022610p:plain

するとB列の値が80以上の行の文字が赤くなりました。

f:id:moko_03_25:20160831022611p:plain

ただしこれで表が完成した場合、このままでは少し問題があります。
下図のように行を挿入すると赤くなる文字がズレました‥
今はまだ「条件付き書式」の情報が残っていて編集する際に厄介なので、これを通常の書式に換えて条件付き書式はクリアしてしまいます。

f:id:moko_03_25:20160831022612p:plain

この時、もう一度「条件付き書式」から「ルールのクリア」を行うだけで書式を残したままクリアがすんなりいく場合と、書式が全て失われてしまう場合があります。
オプション設定なのかエクセルのバージョンなのか‥
とりあえず後者の場合の対処方法を追記しておきます。

まず条件付き書式を外したいセルを選択して一旦コピーします。
次にホームタブの「貼り付け」の右下にあるクリップボードオプションのボタンを押して「すべて貼り付け」ボタンを押して、そのまま上から貼り付けてしまいます。

f:id:moko_03_25:20160831022613p:plain

これで書式自体は移せたので、あとは「条件付き書式」>「ルールのクリア」で条件付き書式をすっきりと除去することができます。

f:id:moko_03_25:20160831022614p:plain

以上です。

エクセルで便利なVBAマクロのメモ

エクセルのVBAで便利な記述の備忘録。
標準操作でできる範囲ならマクロの記録である程度なんとかなりますね。。

A1からA列の最下行の範囲


A列の1行目からA列で何か記入している最下行の範囲を表す場合。

Range("A1", .Range("A" & .Rows.Count).End(xlUp))

 

データサイズのバイト表記をKiB表記にする

A列にデータサイズが並んでいてB列にKiB表記にしたいときはこちら。

' A列を1024で割ったものをB列に入れる
Range("B1").Select
ActiveCell.FormulaR1C1 = "=RC[-1]/1024"
Range("B1").AutoFill Destination:=Range("B1:B" & Cells(2).CurrentRegion.Rows.Count)

' B列を文字列に変えてKB表示にする
Columns("B:B").Select
Selection.Copy
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Application.CutCopyMode = False
Selection.NumberFormatLocal = "0 ""KiB"""

MiB表示にしたいならさらに1024で割ればOK。

A列の値が50以上のA~B列を赤文字・太文字にする

条件付き書式>新しいルール>数式を使用して、書式設定をするセルを決定‥と同じもの。

Columns("A:B").Select
Selection.FormatConditions.Add Type:=xlExpression, Formula1:="=$A1>=50"
Selection.FormatConditions(Selection.FormatConditions.Count).SetFirstPriority
With Selection.FormatConditions(1).Font
.Bold = True
.Italic = False
.Color = -16776961
.TintAndShade = 0
End With
Selection.FormatConditions(1).StopIfTrue = False

 

随時、追記していきます。

秀丸で便利な置換のメモ

秀丸での便利な置換についての備忘録。
ちなみに「秀丸の検索機能を強化するHmJre.dllについて」も併せてどうぞ。

空行を削除


改行しか無い行を削除して詰めてしまいたいときはこちら。

検索 ^¥n

置換

 

○○○を含まない行を削除


ある文字列○○○を含む行は残して、含まない行は削除してしまいたいときはこちら。

検索 ^(?!○○○).+¥n

置換

これを使えば、例えば大量にファイルのパスが並んだリストから、自分が欲しい情報の行だけピックアップするのが楽になります。

○○○を残してそれ以外の文字列を削除


「○○○△△××」という文章から○○○のみを残したい場合はこちら。

検索 ○○○¥f△△¥f××¥f

置換 ¥0


 随時、追記していきます。

秀丸の検索機能を強化するHmJre.dllについて

秀丸正規表現の置換や置換マクロを試していて「ネットで調べた正規表現の置換ができないなぁ」‥と思っていたら、単に付属のdllのバージョンが古かったというだけのことでした。。

という訳でdllについての備忘録。

今お使いの秀丸で使用されている「HmJre.dll」のバージョン確認や設定の方法、そのdllによる機能強化等についてはこちらの記事にまとまっています。

そして公式の配布先はこちら。 

秀まるおのホームページ(サイトー企画)−HmJre.dll

残念ながらdllのみの配布は現在は行われていないようなので、バージョンが古い場合は最新の秀丸本体をDLしてインストールするのが良いようです。

とりあえず秀丸の置換を手元で試してうまくいかない場合は確認してみることをおすすめします。

エクセルで同じ文字列が並んだ行の合計値を出す

エクセルの備忘録。

下図のようにA列に同じ文字列が隣接する場合に、その文字列ごとのB列の合計値を算出‥それを全ての行に対して手軽に行う方法について。
この例だと同じパスのアセットのファイルサイズを合計したい場面になります。

f:id:moko_03_25:20160823023951p:plain

つまりこうなればOKという訳です。

f:id:moko_03_25:20160823023952p:plain

もっと簡単な表でやってみます。
空欄のC1セルを選んで‥

=IF($A1=$A2, "",SUMIF($A:$A,$A1,$B:$B))

と入力します。こちらは我がエクセル師匠に教えてもらいました。
意味は‥
①(IF部分)もしセルA1がセルA2と同じ値なら今選択しているセルC1は空白にする
②(SUMIF部分)IFに該当しないならA列全体の範囲で値がA1と同じ行のB列を合計する

しかしA列の値がA B A B C Aみたいにバラバラだったらうまくいかないのでソートして固めておかないとダメですね。

さてまだ何も表示されません。

f:id:moko_03_25:20160823023945p:plain

セルをだーーっと最下行までコピーします。
するとA列で同じ文字列が続いた場合は最後の行のC列に合計値が入ります。
それ以外のセルが空白のままというのがミソです。

f:id:moko_03_25:20160823023946p:plain

一番頭に一行挿入してC列をフィルタリング。

f:id:moko_03_25:20160823023947p:plain

空白セルを非表示にします。

f:id:moko_03_25:20160823023948p:plain

これで同じ行をまとめてしまって、ついでにB列の合計値を出せました。

f:id:moko_03_25:20160823023949p:plain

結果を別のシートにでもコピー&ペースト。
いらなくなったB列を削除して完成です。

f:id:moko_03_25:20160823023950p:plain

以上になります。

同じ文字列が隣接する場合にその行を削除してしまいつつも直接B列に合計値を上書けたらもっと手間が省けるのですがVBAでやるしか無いんですかね。。
良い方法をご存じでしたらご教授くださいっ。

*翌日の追記*
検索でこちらのページが見つかり、そのままサックリできました!

Sub Sample()
    Dim c As Range
    Dim dic As Object
    Set dic = CreateObject("Scripting.Dictionary")
    With Sheets("Sheet1")
        For Each c In .Range("A1", .Range("A" & .Rows.Count).End(xlUp))
            dic(c.Value) = dic(c.Value) + Val(c.Offset(, 1).Value)
        Next
        .Columns("C:D").ClearContents
        .Range("C1").Resize(dic.Count).Value = WorksheetFunction.Transpose(dic.keys)
        .Range("D1").Resize(dic.Count).Value = WorksheetFunction.Transpose(dic.items)
    End With
 End Sub
(上記サイト様より引用させて頂いています)

ついでにA列B列を削除して値の表示形式をユーザー定義でMiB表記に変えて、一定以上の値は赤字に塗るとかも追記してしまうと良さそうですね。

秀丸の正規表現でパスとアセット名を分離

正規表現の備忘録です。

例えばエクセルでリストを作っている時に、下図のようにパスとアセット名が一緒になった状態からパスとアセット名を別セルに分離したい場面があったりします。

 f:id:moko_03_25:20160823013319p:plain

f:id:moko_03_25:20160823013320p:plain

しかしエクセルの標準機能でのやり方が分からないので、秀丸正規表現で分離することにしました(もっとお手軽な方法があればご教授ください)。

まずはリストを秀丸にコピペします。

f:id:moko_03_25:20160823013321p:plain

次に置換ダイアログを表示。
正規表現をONにして「検索」と「置換」に下図のように入力します。

f:id:moko_03_25:20160823013322p:plain

.+¥¥¥f¥f
¥0¥t¥1

検索欄の文字列の意味は‥
「1文字以上の文字列で末尾は¥」と「以降の文字列」にグループを分ける
文字列の後ろに¥fを追加するとグループ分けできます。
置換欄の文字列の意味は‥
「0番のグループの文字列」「水平タブ」「1番のグループの文字列」
‥です。
元のパスの¥による階層の区切りの数が行によってバラバラですが、検索欄の指定がたったこれだけでOKなのは秀丸正規表現には「最長の一致」という性質があるからのようです。

それから、文字列をグループに分けて置換に元の文字列を残しつつ形態を変える方法についてはこちらの記事でとても丁寧に解説されています。

‥という訳で置換を実行したら下図にようになりました。
全体を選択してコピーします。

f:id:moko_03_25:20160823013323p:plain

エクセルにペースト。はい、分離できました!

f:id:moko_03_25:20160823013324p:plain

もしエクセルにペーストした時にタブスペースを挟んで文字列が別セルに分かれない場合には、ホームタブの「区切り番号」で区切り文字を「タブ」にチェックを入れてからもう一度ペーストしてみてください。

以上になります。

あ、ちなみにセルA1とセルB1の文字列を結合するのは簡単です。
どこかのセルに「=A1&B1」のように入力すれば文字列が合体します。

Particle Randomノードについて

UE4.12からマテリアルにParticle Random Valueというノードが追加されました。
ついにパーティクルごとにランダムな値を与えるノードが‥!

‥という訳でテスト用に組んだマテリアルがこちら。
値を視覚化するためにDebugノードに繋いでいます。

f:id:moko_03_25:20160816004220p:plain

で、Cascadeでエミッターに適用して、数字が見易いようビルボードを横長にしたのがこちら。
あれ‥全く効いていない‥?

f:id:moko_03_25:20160816004221p:plain

‥そこでタイプデータをGPUに変えたものがこちら。
0~1の範囲内でランダムな値が入力されている!
GPUパーティクルで効くということが分かります。

f:id:moko_03_25:20160816004222p:plain

さてこのランダム、何に使うか迷うところですが‥
定番ということでUVの開始ランダムに使ってみます。

f:id:moko_03_25:20160816004223p:plain

はい、見事にランダムになりました!
GPUパーティクルではDynamicParameterが利用できませんが、これでUVの初期位置をランダムにすることができます。ただし上記の構成ではUとVに同じ値が入るのでランダムと言えど斜めにスライドするだけの結果になってしまいますが、もう一工夫加えればもうちょっと崩れた感じにできると思います。

f:id:moko_03_25:20160816004224p:plain

以上、参考になれば幸いです。

パーティクルのLODについて

UE4のエフェクトツール「Cascade」で設定できるパーティクルのLODについて解説します。

パーティクルのLODとは


パーティクルの各種設定をカメラからの距離に応じて変えることができる機能です。
Unreal Engine | パーティクル システムの詳細度 (LOD)

例えば、ゲーム中にエフェクトがカメラから遠い場合はパーティクルの発生数を少なくしたところで見た目の違いはよく分からないので、一定距離を超えると発生数が少なくなるように設定することで計算負荷を抑えるといったことができます。

発生数以外にも変更可能な設定は沢山あります。
各種モジュールのほとんどの項目を変えることができるのではないでしょうか。
このあたりが強力な部分だと思います。
距離に応じてマテリアルを変えることもでき、これには色々と可能性を感じます。

下図は試しにUE4.12でパーティクルにLODを設定してレベルに配置した状態です。

f:id:moko_03_25:20160731015032p:plain

・LOD Level 0 ‥色は黄 / 発生数は秒間20個 / 初期サイズは10 / 距離は0
・LOD Level 1 ‥色は青 / 発生数は秒間5個 / 初期サイズは20 / 距離は300
 ※カメラと3m離れるとLOD Level が1になります

設定する手順


新しくパーティクルシステム(エフェクトデータ)を作成すると、現在のLODレベルは0の状態です。
必要に応じてCascade上部に並んでいる「Add LOD」ボタンを押してLODレベルを増やして、LODレベルごとに各種モジュールの設定を変えて、LODレベルごとにカメラからの距離を指定し、レベルに配置してプレイしてチェックする流れになります。

ちなみにLODを切り替える距離の設定はParticle Systemの詳細の中にあります。
(エミッターが無い空間をクリックすると表示される設定項目です)

f:id:moko_03_25:20160731015034p:plain

 

設定時の注意点


◆作業コストの増大
 LODの設定を細々と行う場合は、その設定自体の作業コストはもちろんのこと、エフェクトの修正時に各LODレベルも修正する必要が出てくるので注意が必要です。
 上記理由から、そのエフェクトデータの見た目がFIXしてから処理負荷対策としてLODレベルを追加して手を入れるというのが良いかと思います。

◆設定しているか一目で分からない
 エフェクトデータを開いてLODレベルをクリックしてみないと分からないので、設定漏れや逆に設定していても気付かずにLOD 0だけ修正してしまうなどのミスが起こり易いと思います。
 一応コンテンツブラウザ上でポップアップ表示される情報に書かれてはいます。
 (デフォルトは0の表示でLODを1つ増やすと2になるので紛らわしいですが。。)

f:id:moko_03_25:20160803100226p:plain

◆基本的には発生時にのみ影響する項目だけ触る
 例えばLODレベルによってSize Scaleの値を変えた場合、エフェクトに近付いたり離れたりすると現在発生している全てのパーティクルのスケールが突然変わってしまうことになります。
 初期サイズの設定であるInitial Sizeの値を変えた場合は、新たに生まれるパーティクルに対してスケールが変わることになります。

◆メッシュパーティクルのメッシュに対しては効果が無い
 LODを設定したメッシュをパーティクルとして飛ばしてもLODの効果はありません。
 また、エミッターで指定しているメッシュをLODレベルごとに変えても切り替わりません。

◆LODでエミッターの表示ON/OFF切り替え時には設定が必要
 デフォルト設定では、一度エミッターがOFFになると近付いたり離れたりしてももうパーティクルは発生しません。しかしCascadeでエミッターのプロパティ「Disabled LODsKeep Emitter Alive」にチェックを入れると再度近付いた時にまた表示されるようになります。特に背景に設置するエフェクトで注意が必要です。

◆ゲームをプレイしてチェックする必要がある
 レベルに配置しただけでなくゲームをプレイしないとLODのチェックができません。
 この辺は不便かも。でも「どのカメラ?」問題があるので仕方ないですね。
 設定したLOD距離を視覚的に表示する機能も欲しいところ。

◆深度ではなくカメラからの距離で変わる
 下図をみると一目瞭然と思います。深度だと思って設定してはダメです。

f:id:moko_03_25:20160731015033p:plain

以上、参考になれば幸いです!


p.s.
新エフェクトエディタ「Niagara」でLODの設定をどう行うのか興味深いです。
ノードベースということで、条件に応じてパーティクルの設定内容を変えたりといったことはかなり自由度が高くなりそうですが、なるべく設定が楽で、かつ設定していることが一目瞭然な見た目になると良いなあと。