第5回.スクリプト(C#)を使って動的マテリアルを作る
はじめに
さて、今回から実際のプログラムに入ります。とはいっても、Shaderを書くわけではなく、スクリプトからMaterialを制御する方法について解説します。
Materialはパラメータの塊
第1回で、Materialは現実世界における素材と同じ立ち位置にあると説明しましたが、実際にはパラメータの集合体です。
パラメータとはテクスチャ(Texture)や色(Color)、数値(Float)、ベクトル(Float4)などのことで、Shaderはこれらのパラメータを使用して描画を行います。パラメータはイラストレーターにとっての参考資料みたいなもの、と考えると分かりやすいかもしれません。(Shaderは現実世界でのイラストレーターなので、参考資料を渡して、これを描いて下さい!と依頼するわけですね)
MaterialはShaderに渡す参考資料セットのようなもの |
パラメータの設定方法
Materialにパラメータを設定するには、主に二つの方法があります。
- Unityのエディタから、プロパティを通して設定する
- スクリプトから設定する
1の方法は第2回で簡単に説明しました。多くの場合このやり方で設定するかと思います。しかしこの方法では値を動的に変更出来ません。今回はパラメータを動的に変更できる、2の方法を解説します。
プログラム
今回は簡単なサンプルとして、水を表現するMaterialを作ってみます。
- メニューのAssets->Import Package->Environmentを選択し、パッケージをインポートします。
- 新規のMaterialを作成して、waterと名前をつけます。
- 使うShaderはStandard Shaderなので、そのままにしておきます。
- ModeをTransparentにして、Albedoの色にRGBA(0,0,0,30)を設定します。
- NormalとDetailNormalにWaterBumpテクスチャを設定します。(左の小さい〇をクリックし、WaterBumpと入力して検索します)
- Secondary MapsのTilingを、Xを2、Yを2にします。
- Smoothnessに0.95を設定します。
- 新しいSceneを作成します。
- Scene上にPlaneを配置し、waterマテリアルを割り当てます。
これで水に見えるMaterialが出来ました。しかし、このままでは水が動かず不自然です。
TextureのOffset値を変更してTextureをスクロールさせ、水の流れを表現してみましょう。
- 手動でOffsetの値を変えると、水の流れが変わる様子を確認できます。
- 新規のScriptを作成し、WaterFlowと名前をつけます。
- 下記のソースを入力します。
- PlaneオブジェクトにWaterFlowをドラッグして追加します。
- WaterFlowのwaterMaterialに、先ほど作成したwaterマテリアルをドラッグします。
- MainFlowには(0.01,0.01)、DetailFlowに(-0.013,0)を設定します。
- 実行すると水が流れるのを確認できます。
using System.Collections; using System.Collections.Generic; using UnityEngine; // 水マテリアルに流れを設定するスクリプト public class WaterFlow : MonoBehaviour { public Vector2 MainFlow; public Vector2 DetailFlow; public Material waterMaterial; void Update() { if (waterMaterial != null) { waterMaterial.SetTextureOffset("_MainTex", MainFlow * Time.time); waterMaterial.SetTextureOffset("_DetailAlbedoMap", DetailFlow * Time.time); } } }
ソースコード解説
MaterialのSetTextureOffsetに、テクスチャ名("_MainTex","_DetailAlbedoMap")と、オフセット量を指定しています。
流れの量に時間を乗算することで、時間が進むほどオフセットのずれが大きくなるため、流れているように見えます。(それぞれのテクスチャ名は、Standard Shaderの中身を調べるとわかります)
waterMaterial.SetTextureOffset("_MainTex", MainFlow * Time.time); waterMaterial.SetTextureOffset("_DetailAlbedoMap", DetailFlow * Time.time);
※ここで実行時に変更されるMaterialの値は、手動で変えた場合と同様に、実行をやめても元には戻りません。
おわりに
今回はScriptから動的にMaterialのパラメータを変更する方法を解説しました。これは一般的なMaterialに限らず、ImageEffectのMaterialでも必ず用いられる方法なので、ぜひ覚えておきましょう。