PlayMaker勉強会 第3回 ～ランタイムでマテリアルをいじろう編～

# PlayMaker勉強会 第3回 ～ランタイムでマテリアルをいじろう編～

社内のSTYLYシーンクリエイター向けに、PlayMaker勉強会を実施しています！
せっかくなので、資料を公開します！

本記事は、第3回の資料ですが、過去の記事を読んでいなくても問題ありません！
興味があれば、読んでいただけると嬉しいです！

##### PlayMaker勉強会シリーズ

- [PlayMaker勉強会 第1回 ～多対多接続はやめよう編～](https://qiita.com/segur/items/24f4f564fd9729b086e7)
- [PlayMaker勉強会 第2回 ～大量ファイル処理はArrayでやろう編～](https://qiita.com/segur/items/10387b874cb4e28667af)
- PlayMaker勉強会 第3回 ～ランタイムでマテリアルをいじろう編～ ← 本記事


## ランタイムでマテリアルのパラメーターを変更したい

たとえば、以下のようにユーザーがスライダーを動かしたら、物体の光沢具合が変わるという仕掛けを作りたいとします！

![correct.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221845/c9c57454-3f8e-0f66-28fa-1dd0fd1c6314.gif)

こういうときは、PlayMakerの [Set Material Float](https://hutonggames.fogbugz.com/default.asp?W406) アクションを使えばいいです！

![SetMaterialFloat](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221845/9c5fa282-ca09-5d37-f03d-015184bcaa2f.png)



上記のように、スライダーの値を `SetMaterialFloat` でマテリアルの `_Metallic` に設定したところ、うまくいきました！


## Unityでは動くのにSTYLYでは動かない…

ここまで作ったもの…Unityでは動きますが、実はSTYLYだと動きません！

ためしにSTYLYで動作確認したものがこちらです！

![wrong.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221845/68a2c51e-7160-636f-cbae-ab3f8acae2eb.gif)

スライダーを動かしているのに、光沢具合が変化しません！

一体なぜでしょう？？


## Unityでは動く理由

さきほどの処理を確認すると、 `SetMaterialFloat` アクションの `Material` 欄に、マテリアル本体を直に設定しています！

![ダイレクトに参照している](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221845/14a18003-af67-d3b3-d5b3-b246d3260287.png)

つまり、Unityでは以下のような参照関係になっています。

GameObjectとPlayMaker FSMが同じマテリアルを参照しているので、PlayMakerで直にマテリアルをいじれば、それがそのまま描画に反映されます。

```mermaid
graph TD
  subgraph Unity
    GameObjectO[GameObject オリジナル]
    FsmO[PlayMaker FSM オリジナル]
    MaterialO[Material オリジナル]

    GameObjectO -->|参照| MaterialO
    FsmO -->|参照| MaterialO
  end
```

とくに問題はなさそうです…


## STYLYでは動かない理由

上記をプレハブにしてSTYLYにアップロードし、それをSTYLYシーンに設置してみたとします。

そのシーンを再生すると、プレハブ[^1]を元にGameObjectやMaterialのインスタンスが生成されます。
[^1]: プレハブではなくシーンファイルの場合もありますし、内部的にはAssetBundleですが、話を簡単にするためここでは**プレハブ**に概念を統一します。

しかしこのとき、 **PlayMaker FSMの参照しているMaterialは、インスタンスではなくオリジナルのまま** なのです！
描画に反映させるためには、MaterialインスタンスをPlayMakerでいじるべきですが、Materialオリジナルの方を参照しているので、いくらいじっても描画に反映されていなかったのでした。

```mermaid
graph TD
  subgraph STYLYへアップロードされたプレハブ
    GameObjectO[GameObject オリジナル]
    FsmO[PlayMaker FSM オリジナル]
    MaterialO[Material オリジナル]

    GameObjectO -->|参照| MaterialO
    FsmO -->|参照| MaterialO
  end
  subgraph 再生中のSTYLYシーン
    GameObjectI[GameObject インスタンス]
    FsmI[PlayMaker FSM インスタンス]
    MaterialI[Material インスタンス]
    MaterialO2[Material オリジナル]

    GameObjectI -->|参照| MaterialI
    FsmI -->|参照先がオリジナルのまま| MaterialO2
  end

  STYLYへアップロードされたプレハブ -..->|実体化| 再生中のSTYLYシーン
  
  style GameObjectI stroke-dasharray:5,5;
  style FsmI stroke-dasharray:5,5;
  style MaterialI stroke-dasharray:5,5;
  style 再生中のSTYLYシーン stroke-dasharray:5,5;
```

## STYLYでも動くようにする

以下のように、 [Get Material](https://hutonggames.fogbugz.com/default.asp?W684) アクションを使って、Materialインスタンスを変数として取得し、それを `SetMaterialFloat` に設定すれば解決します！

![GetMaterial](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221845/70cf0270-4da9-5d5b-d9a7-140dd0e66ed1.png)

STYLYでも無事に動くようになりました！

![correct.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221845/c9c57454-3f8e-0f66-28fa-1dd0fd1c6314.gif)

## おまけ: GameObject参照でもいい

実は他にも解決方法があるので、紹介します。

以下のように、 `SetMaterialFloat` の `Material` 欄は `None` にして、代わりに対象のGameObjectを `GameObject` 欄に指定すれば、STYLYでも動きます！

![GameObject参照](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221845/3e4635d2-bce1-30d7-4b2c-32c692e5cc56.png)

この場合、対象のGameObjectに割り当てられているMaterialインスタンスを自動で見つけてくれるため、正常に動作するんですね！


# さいごに

私はSTYLYのエンジニアをやっているのですが、「Unityではマテリアルがランタイムでいじれるのに、STYLYではいじれない！」という問い合わせを、これまでに何度もいただきました。

このままではまずいと思い、本記事に原因や対策をまとめました。

この問題で悩んでいる多くの人のもとに届くよう願いします。

本記事作成にあたり、以下の記事を参考にさせていただきました！
ありがとうございました！

- [PlayMaker / Action Reference](https://hutonggames.fogbugz.com/default.asp?W2)