[Substance Designer 5 & Unity 5] ProceduralMaterialをインスタンス別に変化させる

sb5_unity5_test2_3

Substance Designerで作ったProceduralMaterialUnity 5で変化させることはできました。

そこから少しだけ発展させて、各インスタンスで独立したパラメーターを与えてみます。

substance = this.GetComponent<Renderer>().sharedMaterial as ProceduralMaterial;

まず前回と同じこの方法ですが、各インスタンスでランダムにパラメーターを渡しても全部見た目が同じになってしまいます。

よく見るとマテリアルの取得がsharedMaterialになってますね。
“shared”、すなわち「共有」なので、これで変化させたパラメーターはシーン中の同じマテリアルを使用しているインスタンスすべてに影響してしまいます。

これを自分自身の専用マテリアルとして変化させたい場合は“shared”を外してあげればOKです。

substance = this.GetComponent<Renderer>().material as ProceduralMaterial;

これで個別に見た目を変えることができました。
実際に動かしてみたのがこの動画です。
http://www.nicovideo.jp/watch/sm26009165

この例では色だけではなく模様もそれぞれ違っています。
ノイズジェネレーターのランダムシードを変化させているのですが、指定する識別子は“$randomseed”です。
ランダムシードの範囲は調べていなかったので仮に0~10としてます。

substance.SetProceduralFloat("$randomseed", Random.Range(0,10));

ProceduralMaterialsubstance.RebuildTextures()してから実際に反映されるまでに若干のラグがあります。
リビルド処理中は変更前のマテリアルで描画されます。

インスタンス生成直後はこれでは問題がある場合もあるので、インスタンスを作ったらすぐにGetComponentInChildren<Renderer>().enabled = false;で描画を無効にしておいて、それからマテリアルを変化させます。
そしてインスタンス側のUpdateイベントで、こんな感じでリビルド完了を監視して描画を有効にしています。

void Update () {
  if(!this.GetComponentInChildren<Renderer>().enabled) {
    if(!substance.isProcessing) this.GetComponentInChildren<Renderer>().enabled = true;
  }
}

この方法を使えば、マテリアルが完成してからオブジェクトが出現します。
使わなければオブジェクトはすぐに出現しますが、その時点ではマテリアルは初期値のままで、少し遅れて正しいマテリアルが反映されます。

どちらがよいかはゲーム内容やそのときの状況によるので、フラグを持たせて両方に対応できるようにしておくといいかもしれません。