UE4 メッシュの一部の色だけをパラメータで切り替えられるマテリアルを作る
上記のブログ等で物体全体の色をパラメータで切り替えるなどは紹介されているが一部だけの色を切り替えるみたいなものは見つけられなかったのでそれを自前で実装した。マテリアル全体の構成は以下の通り。
ちなみに今回、マテリアルはSubstancePainterで作成した。
テクスチャの色域を指定してマスクテクスチャを作る
Photoshop等でマスクテクスチャを用意するのが最も簡単だろうが今回はマテリアルエディタ内でマスクテクスチャを作ってみる。
抜き取りたい色を "Const3Vector"で用意。それを "Distance"のBに繋ぐ。
このままではグレーの部分が出てしまうのでifノードを使って0と1でくっきり分ける。これで紫部分をくり抜けるマスクテクスチャを作ることが出来る。
一部分だけ色を変更したテクスチャを作る
"JumpColor"という3Vectorパラメータを作成。この色で紫部分を塗りつぶす。
生成したマスクテクスチャと"JumpColor"を掛け合わせ、反転させたマスクテクスチャと元々のBaseColorテクスチャを掛け合わせたものを足すことで一部だけを"JumpColor"で塗りつぶすことが出来る。
Switchでもとの色と塗り替えた色を切り替える
Static Boolパラメータ、"IsJump"を用意。これをSwitchノードのValueに繋ぎ、Trueに"JumpColor"で一部を塗りつぶしたテクスチャを、Falseに元々のテクスチャを繋ぐ。
これでIsJumpの切り替えで一部の色だけを切り替えるマテリアルが作れた。
(続き)
Pythonで二次元ランダムウォーク+matplotlib.animationのgif保存
大学の講義にてPythonでランダムウォークを実装するのに初歩的なところでハマったのでメモ。プログラムは以下の通り。
%matplotlib nbagg # -*- coding: utf-8 -*- # モジュールのインポート import random import numpy as np import matplotlib.pyplot as plt import matplotlib.animation as animation # メイン実行部 # 試行回数nの初期化 n = int(input("試行回数nを入力してください:")) fig = plt.figure() ims = [] x = 0.0 y = 0.0 # グラフ描画の準備 xlist = [x] # x座標 ylist = [y] # y座標 # ランダムウォーク for i in range(n): x += (random.random() - 0.5) * 2 y += (random.random() - 0.5) * 2 xlist.append(x) ylist.append(y) im = plt.plot(xlist, ylist, marker='o', color = 'r') #im = plt.scatter(xlist, ylist, marker='o', color = 'r' ims.append(im) # グラフの表示 ani = animation.ArtistAnimation(fig,ims,interval=100) ani.save('test1.gif', writer='imagemagick') plt.show()
引っかかったのは
im = plt.plot(xlist, ylist, marker='o', color = 'r') #im = plt.scatter(xlist, ylist, marker='o', color = 'r' ims.append(im)
のところ。今回はplotでアニメーションさせろって条件だったのでこれで上手くいくのだが、matplotlib.scatterでアニメーションさせる時は
ims.append([im])
と明示的にimをリストに変えなければならない模様。逆にplotの時にimをリストとしてappendすると上手く行かない。これはmatplotlib.plotの返り値が最初からリストになっているせい。
おまけ: Win10 × Jupyter Notebookでmatplotlib.animationの結果をgif保存する方法
おそらく何も設定を変更せずani.save()しても MovieWriter imagemagick unavailable. などと表示され失敗すると思う。これは下記のサイトの指示に従って設定ファイルを変更すれば解決するはず。しかし、ウチの環境では Install-Package imagemagick が上手く動かなかったので こちらのサイト から直接インストーラーをDLした。
イベントディスパッチャーを使ってUMGの文字を変える
前回の続き。
UMGの詳細パネルからプロパティに関数バインディングすると毎フレーム処理が走ってしまい良くない。今回はその一つの解決法。
イベントディスパッチャーを使って必要な時だけ関数を呼び出す
今回はThirdPersonCharacterが持つInteger変数をUMGのTextに表示させるということをしてみる。
UMGのDesigner編集画面でTextを追加。詳細パネルでIs Variableにチェックを入れると"TestTextBlock"をBP上で変数として扱うことが出来る。
ThirdPersonCharacterのBP編集画面を開き、Integer変数、testCountと、イベントディスパッチャー、ED_CountUpdateを追加。ED_CountUpdateの詳細パネルで画像の様にInputsを編集するとIntegerを入力に取るイベントをバインド出来るようになる。
ThirdPersonCharacterでは画像のようにBPを組む。キーボードのUを押すとTestCountがインクリメントされディスパッチャーが発行される単純なもの。
UMGに戻り、画像のような関数、SetTextBlock_Textを用意。
EventGraphでは次の画像の様にBPを組む。ThirdPersonCharacterでディスパッチャーが発行されたらEventCountUpadateが実行され、その中で先程作った関数が呼び出される。
いつもの様にレベルBPでUMGをCreateしAdd to Viewport。
実際動かしてみたのが以下。
TestCountが変更されたときだけディスパッチャーが発行され、UMGを更新することが出来た。
Event Constructの話
最初、キャラクターのBPのEvent BeginPlayでディスパッチャーをCallしてSetTextBlock_Text関数を呼び出そうとした。
これでEvent BeginPlayが起きた時にディスパッチャーがCallされ、0で初期化できると思ったのだが……
0で初期化されない。OutputLogを見てみるとUMGのEvent Constructが呼ばれる前にキャラクターBPのEvent BeginPlayが呼ばれている。バインドする前にCallしてしまっているのが原因だった。
色々調べるとEvent ConstructはAdd to Viewportする時に呼ばれるものらしいが。現状これに対する解決策が浮かばなかったのでEventConstructで直接SetTextBlock_Textを呼ぶことで無理やり解決した。
UMGの詳細パネルから関数を作ってバインディングするのは良くない
今日Twitterで教えてもらい知ったこと。下の記事でも使っているテクニックのUMG要素の制御関数を詳細パネルで作るのは良くない。
それを確かめるのに簡単なテスト。UMGを作成し、Textを配置、そこからバインディングする関数Get Text 0を追加してみる。
関数の実装はこんな感じ。関数が呼ばれるたびにPrint Stringするだけの単純なもの。
作成したUMGをレベルブループリントで追加してPlayしてみると
関数Get Text 0が毎フレーム呼ばれている!
これまで何故かこの方法で作成した関数は参照した値が書き換わる時だけ呼び出されるものだと思っていた。よく考えれば毎フレーム呼ばれるのは当然の事。
Event Tickが毎フレーム呼ばれると非常に処理が重くなるのはぷちコンの時に痛いほど学んだので、最近はCustom EventやPure関数、ディスパッチャーやEvent Begin Playで変数代入など色々工夫するようにしていたのだが思わぬところに落とし穴があった。こんな基本的な事見落としていたなんて……
というわけでこれからはこの方法を使うのは(基本的には)止めていこう。
Blutilityで遊んでみる(2) UE4.20 コンテンツブラウザ上でアセットの詳細設定を一括で変更する
以下の記事でボクセルモデルをFBXとして取り込む時、テクスチャの設定を
Compression -> Compression Setttingを "UserInterface2D"に変更
Texture -> Filterを "Nearest" に変更
Level Of Detail -> Texture Groupを "2D Pixels" に変更
の様に変更する必要があることがわかった。しかし毎回この設定を手作業でするのもめんどくさいよなーってことで、Blutilityを使って自動化してみた。
実装
Editor PrefernecesでBlutilityを有効化している事を確認し、Blutilityを作成。今回は親クラスにActorActionUtilityを指定する。これはUE4.20で追加予定の機能で、これを親に指定することでBlutilityをコンテンツブラウザ上から直接実行できるようになる。関数を作成しの画像の様なBPを組む。
Get Selected Assetsで選択したアセットを読み込み、Textureにキャストして設定を書き換える、いたって単純なBP。これでコンテンツブラウザ上で対象のテクスチャを右クリックしScript Actionから呼び出すことができるようになる。
これで設定を変更することができる……のだがここで問題発生。確かに設定は変更されているがBlutility関数「Change Voxel Setting」を実行することでテクスチャのボケが解消されるはずなのにされない。
この問題はBlutilityを実行後Reimportを押すことで解決する。
(GIF画像の為適用されてるのか分かり辛いのはゴメンナサイ…)
せっかく自動化したのにReimportの手間がかかるのは残念だが現状BP上からReimportを掛ける関数がないようなので仕方ない。全部手作業で変更する手間を考えればよっぽどましと考えるしかない。
Blutilityで遊んでみる(1) レベルエディタ上でActorのスケールを変更する
先日UE4.20のPreview1が公開された。で、このverで前々から気になってたBlutilityの機能がちょっと拡張されたらしいのでちょっと遊んでみた。詳しい手順は以下の記事が分かりやすい。
ざっくり説明するとエディタ上でブループリントを実行できるという機能。UI拡張は出来ないがC++を書かずにある程度の機能拡張ができるというのが魅力。まだまだ実験段階でやれる事は少ないが可能性を感じる。
とりあえず今回はActorのスケール値を二倍or二分の一にする関数を実装してみる。
実装
上記の記事に従いBlutilityを使えるようにし、コンテンツブラウザで作成。この時親クラスは 「ActorActionUtility」 とする。
コンテンツブラウザ上で右クリック->「ブループリントを編集」でブループリントを編集できる。関数「ActorScale 2times」と「ActorScale oneHalf」を作成。
中身はこんな感じ。oneHalfの方は掛ける値を0.5に変更するだけなので省略。特に説明することのない基本的なもの。
続いてこのBlutilityの対象をActor継承クラスだけに制限するために関数のオーバーライドで「GetSupportedClass」を書き換え。Return NodeにActorを設定する。
このBlutilityはレベルエディタ上でActor継承クラスを選択した状態で右クリック->Scripted Action で使用可能。実際使った様子がこちら。
詳細パネルでScaleを直打ちしたほうが早い気もするが、Actorを複数選択した状態でこのBlutilityを実行すればそれぞれのScale値を基準に二倍してくれるのでその点においては良いかも。ただしUndoが効かないのが難点。
謎
最初画像下の「Get Selected Assets」を使ってうまくいかなかったのだが、上の「GetSelection Set」に変更したら機能した。この2つの違いはよくわかってない。
まだまだ実験段階であるが色々できそう。しばらくこれで遊んでみるかも。