読者です 読者をやめる 読者になる 読者になる

第5回.スクリプト(C#)を使って動的マテリアルを作る

はじめに

 さて、今回から実際のプログラムに入ります。とはいっても、Shaderを書くわけではなく、スクリプトからMaterialを制御する方法について解説します。

Materialはパラメータの塊

 第1回で、Materialは現実世界における素材と同じ立ち位置にあると説明しましたが、実際にはパラメータの集合体です。
 パラメータとはテクスチャ(Texture)や色(Color)、数値(Float)、ベクトル(Float4)などのことで、Shaderはこれらのパラメータを使用して描画を行います。パラメータはイラストレーターにとっての参考資料みたいなもの、と考えると分かりやすいかもしれません。(Shaderは現実世界でのイラストレーターなので、参考資料を渡して、これを描いて下さい!と依頼するわけですね)

MaterialはShaderに渡す参考資料セットのようなもの



パラメータの設定方法

Materialにパラメータを設定するには、主に二つの方法があります。

  1. Unityのエディタから、プロパティを通して設定する
  2. スクリプトから設定する

 1の方法は第2回で簡単に説明しました。多くの場合このやり方で設定するかと思います。しかしこの方法では値を動的に変更出来ません。今回はパラメータを動的に変更できる、2の方法を解説します。

プログラム

今回は簡単なサンプルとして、水を表現するMaterialを作ってみます。

  1. メニューのAssets->Import Package->Environmentを選択し、パッケージをインポートします。
  2. 新規のMaterialを作成して、waterと名前をつけます。
  3. 使うShaderはStandard Shaderなので、そのままにしておきます。
  4. ModeをTransparentにして、Albedoの色にRGBA(0,0,0,30)を設定します。
  5. NormalとDetailNormalにWaterBumpテクスチャを設定します。(左の小さい〇をクリックし、WaterBumpと入力して検索します)
  6. Secondary MapsのTilingを、Xを2、Yを2にします。
  7. Smoothnessに0.95を設定します。
  8. 新しいSceneを作成します。
  9. Scene上にPlaneを配置し、waterマテリアルを割り当てます。

f:id:IARIKE:20170301223913p:plain

 これで水に見えるMaterialが出来ました。しかし、このままでは水が動かず不自然です。
 TextureのOffset値を変更してTextureをスクロールさせ、水の流れを表現してみましょう。
f:id:IARIKE:20170301224039p:plain

  1. 手動でOffsetの値を変えると、水の流れが変わる様子を確認できます。
  2. 新規のScriptを作成し、WaterFlowと名前をつけます。
  3. 下記のソースを入力します。
  4. PlaneオブジェクトにWaterFlowをドラッグして追加します。
  5. WaterFlowのwaterMaterialに、先ほど作成したwaterマテリアルをドラッグします。
  6. MainFlowには(0.01,0.01)、DetailFlowに(-0.013,0)を設定します。
  7. 実行すると水が流れるのを確認できます。
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でも必ず用いられる方法なので、ぜひ覚えておきましょう。