[Substance Designer 5 & Unity 5] ProceduralMaterialを使ってみた

sb5_unity5_test1_1

今回の実行動画はこちら。
http://www.nicovideo.jp/watch/sm26001457

Substance Designerで作ったマテリアルをUnityでテクスチャとして利用するというのはやっていましたが、UnityScriptSubstanceのパラメータをコントロールするというのはやったことがありませんでした。

参加中の某プロジェクトで、状況に応じてテクスチャのブレンド率を変化させるという演出を加えたいと思っていたので、ちょっと試してみました。

今回は基礎だけできればよかったので、シンプルに単色のコントロールです。
Substance Designer側はこんな感じです。出力カラーをエクスポーズして“base_color”と名前をつけました。
sb5_unity5_test1_2

このsbsarUnityでインポートして、メッシュのマテリアルに適用する…というところまでは今までにやってきたので特に詰まることもなく、Unityのインスペクタでも“base_color”がちゃんと反映されていて色の調整もできました。

さて、ここからが本題で、この“base_color”をスクリプトでコントロールすることにします。
まずはAllegorithmic公式のチュートリアルを見てみます。
https://www.youtube.com/watch?v=Rq_Hl5LZW8U

このチュートリアルを参考にスクリプトを書いてみましたが、これはUnity 4時代のものなので、一部の命令がUnity 5では変ってしまっています。
ただその箇所はUnityが勝手に修正してくれました。

とりあえず“base_color”を操作するためにsubstance.SetProceduralColor(“base_color”, new Color(r, g, b, 1.0F));と書いてみました。

しかし、エラーは出ないのに何も変化がありません。
substance.GetProceduralColor(“base_color”)してみるとrgbaが全部0.0になっています。

どうやら“base_color”が認識されていないようです。
ここで結構な時間悩みましたが、何気なくインスペクタ上の“base_color”の名前の上にマウスカーソルを合わせてみると、ポップアップに“BaseColor”という文字が…。

試しにsubstance.GetProceduralColor(“BaseColor”)してみると、rgbaにちゃんとインスペクタ上の初期値と同じ色が入ってました。

この辺りがUnityのめんどくさいところなんですが(ちゃんと調べてみました)、気を取り直して「状況に応じて変化させる」の第一段階としてマウスクリックしたときの座標で色を変化させるというスクリプトを書いてみました。

using UnityEngine;
using System.Collections;

public class cube1_test : MonoBehaviour {

    public GameObject mySubstanceObj;
    private ProceduralMaterial substance;
    private string base_color = "BaseColor";

    void Awake() {
        //substance = renderer.sharedMaterial as ProceduralMaterial; ← Unity 4での書き方
        substance = mySubstanceObj.GetComponent<Renderer>().sharedMaterial as ProceduralMaterial;  // ← Unity 5ではこう変った
        if (substance == null) {
            Debug.Log("substance error");
        }
        substance.cacheSize = ProceduralCacheSize.Medium;
        ProceduralMaterial.substanceProcessorUsage = ProceduralProcessorUsage.All;
    }

    void Start () {
        substance.CacheProceduralProperty (base_color, true);    
    }
    
    void Update () {
        if(substance) {
            if(Input.GetMouseButtonDown(0)) {
                float sx = substance.GetProceduralColor(base_color).r;
                float sy = substance.GetProceduralColor(base_color).g;
                float sz = substance.GetProceduralColor(base_color).b;
                float px = Mathf.Max(0.0F, Mathf.Min(1.0F, (float)((int)Input.mousePosition.x % 200) / 200.0F));
                float py = Mathf.Max(0.0F, Mathf.Min(1.0F, (float)((int)Input.mousePosition.y % 200) / 200.0F));
                float pz = Mathf.Max(0.0F, Mathf.Min(1.0F, (px + py) / 2.0F));
                substance.SetProceduralColor(base_color, new Color(px, py, pz, 1.0F));
                substance.RebuildTextures();
                Debug.Log(sx.ToString() + " , " + sy.ToString() + " , " + sz.ToString() + " --> " + px.ToString() + " , " + py.ToString() + " , " + pz.ToString());
            }
        }
    }
}

これを実際に動かしてみたのが最初の動画です。

以前はこういうことをやるためにわざわざ自分でシェーダーを書いていましたが、Substanceならこんなに簡単にできちゃうんですね。

Substance Indie Packは以前から使用していましたがこれまでは単に高機能なテクスチャ製作ツールとしてしか見ていませんでしたが、今後はもっと活用できそうです。