今回は個人的に気になったのでマテリアルのTimeノードについて調べてみました。
Timeノードはマテリアルで経過時間を取得する命令ですが、そもそもこの時間とはいつからの時間なのか?単位は何なのかわかりません。
UE4のドキュメントにも、時間の推移をマテリアルに渡す、としか書いてありません。
というわけで調べてみました。
調べる方法はソースコードを読むより試したほうが早いだろうってことでマテリアルを作って試しました。
まず、以下のマテリアルを作成し、このマテリアルを貼ったオブジェクトをレベルに配置しました。
Timeを1/10して、1.0になったらエミッシブが赤くなります。
UE4ではたいていの時間の単位が秒ですので、Timeノードも同様であれば10秒で赤くなります。
また、予想としてはアプリ開始時からの時間と思われるので、実行して10秒後に赤くなればこの予想も的中です。
で、試した結果はビンゴ。
Timeノードは単位が秒で、アプリ開始時からの時間を計測していると考えられます。
しかし他にも可能性はあります。
1つはマテリアルを使ったオブジェクトの生成時から時間という可能性です。
オブジェクトはレベルに配置されていたため、この時間はアプリの開始時間とほぼ同じです。
というわけで、今度は以下のようにレベルBPを作成し、アプリ開始から5秒後に配置しているオブジェクトとは別のオブジェクトを生成してみました。
生成したオブジェクトも前述のマテリアルを適用済みです。
結果は同時に赤くなりました。
オブジェクトの生成時間はTimeノードに影響を与えません。
しかし、同じマテリアルアセットだったから同じTimeノードの結果になったのでは?
というわけで今度は別のマテリアルアセット、加えてDynamic Material Instanceも試してみました。
結果は前回のものと変わらず。
マテリアルアセットの違いやInstanceの違いもTimeノードには影響を与えません。
最後はレベルです。
アプリの開始=レベルの開始ですので、今の状態ではTimeノードがアプリ開始からの時間かレベル開始からの時間かわかりません。
そこで、OpenLevelを使って別のレベルに移動、そこのレベルにも前述のオブジェクトを配置してみました。
結果はビンゴ!
レベルが移動するとTimeノードの結果はリセットされ、0から再カウントされました。
StreamLevelではどうかと試してみましたが、こちらはカウントがリセットされませんでした。
結論!
マテリアルのTimeノードはPersistentレベルの開始時からカウントされ、単位は秒!
さて、これだとちょっと困ることもあります。
UVスクロールやエミッシブの明滅などをTimeノードで実装した場合、同一レベルに配置された複数のインスタンスにおいて同じタイミングでスクロールや明滅が発生することになります。
例えば炎の明滅がすべて同じタイミングで発生していたりすると、はっきり言って違和感が出てきてしまいます。
これを解決する方法はいくつかありますが、一番簡単な方法を続きからで紹介しています。
ついでに、おまけのマテリアルも。
さて、解決方法ですが、1つの方法としてはTimeノードを使用せず、外部からタイムラインなどを利用してパラメータをマテリアルに渡す方法があります。
この方法の利点はタイムラインによって複雑な動きも実装できるという点です。
例えばUVスクロールをTimeノードで実装すると等速運動には使いやすいですが、変則的な動き(ある段階で停止、一定時間後にまた動くとか)は作りにくいです。
タイムラインを使えばこのような変則的な動きにも柔軟に対応できます。
ただ、私のこれまでのゲーム開発経験では、そのような変則的なUVスクロールやマテリアルアニメーションは稀にしか使われません。
UVスクロールなどはそのほとんどが等速直線運動でした。
アニメーションを別ファイルで定義できるように実装することがほとんどでしたが、やっていることはDeltaTimeに係数を積算すればいいだけという結果だったりします。
というわけで別の解決策として、ランダム値をConstruction Scriptで渡すという方法をとってみます。
多分、これが一番簡単な実装方法です。
まず、Starter ContentsにあるM_Tech_Hex_Tile_Pulseというマテリアルを改造しましょう。
このマテリアルは4秒周期でエミッシブの色が変化します。
エミッシブをブレンドするためにTimeノードを使用している部分を以下のように変更します。
TimeRandomというパラメータは外部から与えるようにします。
次にStatic Meshを持ったBPを作成し、Construction Scriptで以下の様な処理を行います。
floatのランダム値が0~4.0の範囲で生成され、これがTimeRandomに渡されます。
あとはこのBPから複数のインスタンスを生成してやればそれぞれのインスタンスでエミッシブの変化タイミングが変わります。
で、おまけ。
こういう溝にエミッシブで色が乗るのって場所によって変化してくれたほうが未来っぽいですよね。
血液が流れていくような感じというか、そういうやつ。
というわけで、エミッシブの部分を以下のように変更してみましょう。
真ん中辺りでサンプリングしているマスクテクスチャは黒から白へ、そしてまた黒へとグラデーションしている256*4のテクスチャです。
これを床に貼り付けてパラメータを調整した結果がこちらです。
アクター中心から光が外に向けて、定期的に移動していますね。
今回はある位置から放射状に流れるようにしましたが、マスクテクスチャとUVの調整で一定方向に流したりすることも可能です。
近未来の都市や失われた超古代文明とかで出てきそうなエフェクトですが、ボスから放射状に伸びるエネルギー波などの演出にも使えるでしょう。
Timeノードは使い道が多数ある素晴らしいノードです。
動きのあるシーンというのは単純でも見ているとワクワクしてきますよね。
そういうシーンのためにTimeノードを利用した各種マテリアルはいかがでしょうか?