【第14回/Appendix】ブループリントでマテリアルインスタンスの値を変更する
概要
ブループリントでマテリアル(インスタンス)の値を変更する処理を作成します。
特定の条件でアイテム(BP_KeyStone)のエミッシブ(Emissive)値を変化させてみましょう。
マテリアルインスタンスについて忘れてしまった場合は、過去にさかのぼって見直してみてくださいね。
変更したいマテリアルの値をパラメータ化しておく
まず前提として、ブループリントで色などを変更するには、マテリアルエディタ上でパラメータ化しておく必要があります。
マテリアルインスタンスの場合、図の囲まれた値が変更できるということですね。
変更するときには「パラメータ名」で指定することになりますので、わかりやすい名前にしておきましょう。
なお次項で説明するため、使用するマテリアルのOpacityをパラメータ化して、マテリアルインスタンスでデフォルトカラーを青め、Emissiveを0に調整しておきました。
マテリアルの参照を作成する
マテリアルを処理するための参照を作成しておきます。
ブループリントエディタを開きます(BP_KeyStone)
コンポーネントパネルからStatic Meshコンポーネントの参照を設置します。
出力ピンからワイヤーを伸ばし「Create Dynamic Material Instance」ノードを検索して設置します。
これはマテリアル・インスタンス・ダイナミクス (MID)と呼ばれる機能で、メッシュからマテリアル参照をつくるために必要な手順と考えてください。
ノードを配置したら、「Return Value」ピンから変数化しましょう。
これでメッシュの参照が作成されました。
「Begin Play」イベントに接続して、ゲーム起動後すぐに処理が実行されるようにしておきます。
このとき、ひとつだけ注意してほしい点があります。
下図のように、メッシュに複数のマテリアルが設定されている場合は引数の設定が必要です。
変更したいマテリアルスロットの番号に合わせた「Element Index」を指定しなければなりません。たとえば、メッシュの「エレメント1」に設定されたマテリアルを変更したい場合は、「Element Index」を「1」に指定します。
ですので、同じメッシュから別々のマテリアル参照を作りたい場合は、複数個指定することになりますね。
今回のメッシュはマテリアルがひとつなので気にしなくて(変更しなくて)大丈夫。
そのまま進めましょう。
パラメータを変更する
パラメータを変更する処理を確認してみましょう。
ひとまず覚えておきたいノードは2つです。
ノードはマテリアル参照変数からワイヤーを伸ばして検索します。
「Set Vector Parameter Value」は、色パラメータなどに使用しているVector値を変更するときに使います。
「Set Scalar Parameter Value」は、メタリックやラフネスなどに使用しているScolar値を変更するのに使います。
その他にもテクスチャを変更するノードなどもあります。余裕があれば調べてみてください。
さっそく変更してみましょう。
参照の作成後、「Delay」を挟んで実行してみます。
マテリアル参照変数からワイヤーを伸ばして「Set Scalar Parameter Value」を検索して配置します。
変更するパラメータ名と値を指定しましょう。
パラメータ「Emissive」を変更してみます。
シミュレートプレイで確認してみましょう。
開始直後、ウェイトを置いてからEmissive値が「0」から「10」になりました。
少々わかりづらいですが、値は反映できているようですね。
あとは処理を調整して、どこでどのように呼び出すかを決めるだけです。
タイムラインを使って点滅させるようにする
復習もかねて、タイムラインを使って値を変更してみましょう。
右クリックして「Timeline」と検索して配置します。
タイムラインエディタでグラフを追加します。
2秒間隔で0~70の山にしました。
開始すぐに動作するように、またタイムラインがループするように「オートプレイ」と「ループ」にチェックを入れておきます。
ノードを接続して確かめてみましょう。
うまく動作できたようですね。
今回は以上です!
他のメッシュやパラメータを変更させてマテリアルの変更に慣れておきましょう。
(補足)呼び出し処理を作る
ためしに、プレイヤーが近くによったときに光る処理を作ってみます。
コリジョンで囲んで「On Component Begin Overlap」などで判断してもいいですが、タイマーで指定秒数ごとに距離を測って確認する処理にしてみます。
タイマーを作成します。以前は「Set Timer by Function Name」を使いましたが、今回は「Set Timer by Event」を使ってみます。
これは「Set Timer by Function Name」のようにイベント名を指定する必要がありません。
「Event」ピンに接続されたイベントをタイマー実行します。
イベントディスパッチャーの接続に似ていますね。
「Event」ピンからワイヤーを伸ばしてカスタムイベントを追加します。
つぎにアクタとプレイヤーの距離を測ります。
「Get Distance To」ノードを配置しましょう。
これは、ターゲット(自身)とOtherActorとの距離を返すノードです。
もうひとつの「Get Horizontal Distance To」ノードは、Z軸方向を無視した距離を取得します。
「Get Player Pawn」を配置して「Other Actor」ピンに接続しましょう。
次の図はタイマーが実行されるたび、距離が50m以内であれば、タイムラインを1回実行するようにしたものです(タイマーのループとオートプレイは切っておいてください)。
自身のアクタ座標とPlayer Pawnのアクタ座標を減算(Vector - Vector)で求める方法も記載しておきます。「Vector Length XY」ノードは高さ(Z軸方向)を無視したVectorの長さを取得するもので、平面距離を取得するときなどに使います。
検出方法はさまざまです。
そのゲームに合った検出方法を探してみましょう。
たとえば、カメラでアクタが描画されているか分岐する方法なども面白いかもしれませんね。
お疲れさまでした!