【NeosVR】アバターの明るさをコンテキストメニューから切り替えられるようにする

![2021-07-30 13.47.17.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/83116/e7d4f6af-1282-753d-3b1b-45b5afc43ccf.jpeg)
こんにちは(ﾋﾟｶｰ)

ユーザーが自由にワールドをアップロード出来るNeosVRやVRChat、Clusterなどでは環境光設定がワールド投稿者毎に異なるため、場所と使用シェーダーの組み合わせによっては上図のようにアバターの表示が酷い状態になるという問題があります。

NeosVRでは特にXiexeToonShaderを使用している状態でRenderQueueの値を2501に設定した場合に発生しやすくなります。
かといってデフォルト値の-1に戻すと今度はPostProcessの影響を受けるようになってしまい、アバターに陰影が発生し印象が変わってしまいます。

![20210730165530_1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/83116/2e21377f-f99e-c8dc-c198-cb22b4beadad.jpeg)
白飛びは反射光が強いことが原因なので、AlbedoColorの設定値を低くすることで明るさを抑えることが可能です。

![20210730171845_1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/83116/f1329c41-de45-df08-399a-61112b16413c.jpeg)
が･･･そうすると今度は暗いワールドへ行った際に真っ黒クロスケ･･･は言いすぎですが暗さが気になってしまいます。
自分一人だけならまだいいのですけど、正常な色の人と一緒にいると本当に気になります･･･。

環境光自体を調整するというのもNeosVRなら可能ではありますが、セッションでの権限が必要であること、環境光の調整は他人のアバターに影響を与えてしまうことなどから自分のアバター側を調整出来るようにするのが良いと思っています。

![path4529.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/83116/3302efba-c575-178b-3d52-466941626d51.png)
そのため、このようなコンテキストメニューを作成し、マテリアルのAlbedoColorを変更できるようにすることでアバターの明るさを自分で切り替えられるようにします。

###補足
![20210730160221_1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/83116/973ad4da-2f2a-942b-30e7-a1d5d8bf5e4f.jpeg)
AlbedoColorはXiexeToonでは単にColorという名前になっています。

#前提条件
シェーダーの設定値を変更する必要があるため、マテリアルがアバターオブジェクトの中に組み込まれている必要があります。
組み込まずに設定した場合、おそらくその場では動くのですが再度アバターを着た際にマテリアルの参照が外れ、動作しなくなるはずです。

![context_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/83116/8d2ae735-a0a9-d8cd-8100-c9af07e0d1cf.png)
マテリアルをアバターオブジェクトの中に組み込む簡単な方法として、モデルインポート時にアセットをオブジェクト内に入れるオプションにチェックを入れるという方法があります。

![20210730144416_1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/83116/cb58083a-818f-03dc-2239-79b1b92afa74.jpeg)
チェックを入れてインポートした場合、CenteredRoot配下にマテリアルが格納されています。

もし、現在使用しているアバターがモデルインポート時該当オプションにチェックを入れておらず、再度モデルインポートしてその他の設定をするのも嫌という場合は

ComponentCloneTipを使ってシェーダーコンポーネントを1個ずつアバターオブジェクト内に移動
→MeshRendererの参照マテリアルを修正

とすることでマテリアルがアバターオブジェクトの中に組み込まれた状態にできます。

#コンテキストメニュー作成
コンポーネントを使用し、コンテキストメニューを作成します。

##1.スロット作成

管理しやすくするため、アバターオブジェクト配下にContextMenuという名前で空オブジェクトを作成し、更にその配下にAlbedoColorという名前で空オブジェクトを作成します。
![20210730151249_1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/83116/593b3f95-db0d-59b1-5497-80f1603ad628.jpeg)

##2.コンテキストメニュー項目作成

###コンポーネント追加
手順1で作成したAlbedoColorスロットに以下のコンポーネント6種を追加します。

**①RootContextMenuItem**
Radiant UI
->Context Menu
->RootContextMenuItem

**②ContextMenuItemSource**
Radiant UI
->Context Menu
->ContextMenuItemSource

**③SpriteProvider**
Assets->
SpriteProvider

**④ButtonValueCycle\<color>**
Common UI
->Button Interactions
->ButtonValueCycle\<T>
->color

**⑤ValueMultiDriver\<color>**
Relations
->ValueMultiDriver\<T>
->color

**⑥ValueTextFormatDriver\<color>**
Utility
->ValueTextFormatDriver\<T>
->color

###コンポーネント設定

![20210730154508_1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/83116/4069239c-456d-9a51-9f86-ae4516e54ebd.jpeg)
コンテキストメニューに項目を追加するため、RootContextMenuItemのItemにContextMenuItemSourceをセットします。
追加された項目はボタンとなり、メニューを開いて押すことでボタンイベントが発生します。

![20210730155907_1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/83116/aa7601de-5780-2f03-edf5-e83e7ba61294.jpeg)
アイコンを設定出来るようにするため、ContextMenuItemSourceのSpriteにSpriteProviderをセットします。

![20210730160054_1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/83116/0f109546-9e5f-6731-0739-493aa9461b6d.jpeg)
SpriteProviderに任意のテクスチャを設定します。
ここで設定したテクスチャがコンテキストメニュー上で表示されるアイコンになります。

![20210730161938_1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/83116/9a0f5a60-7c0c-8745-6d95-617bf8f9200f.jpeg)
ButtonValueCycle\<color>のValues(list)でAddボタンを押下し、AlbedoColorの組み合わせをいくつか用意します。
必要な数値や設定数などはあなたの使用アバターや好みで大きく変化します。今回は0.9、0.7、0.5の3つの組み合わせを用意します。

![20210730162259_1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/83116/7fc8e5bc-ec9b-8693-96f7-45f6c95a22a4.jpeg)
複数マテリアルのAlbedoColorを一括で変更したいため、
ButtonValueCycle\<color>のTargetValueにValueMultiDriver\<color>のValueをセットします。

![20210730163025_1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/83116/5e114ee8-6fbb-0484-3338-e28be5c532e0.jpeg)
ValueMultiDriver\<color>のValueをValueTextFormatDriver\<color>のSourceにセットします。

![20210730163314_1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/83116/b8e65456-b1c5-8546-e34c-1bd3965d2465.jpeg)
ValueTextFormatDriverのFormatに「AlbedoColor\<br>{0}」と入力します

![20210730163555_1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/83116/ea9d511a-9d2f-b4fc-6897-e79380a70e19.jpeg)
ContextMenuItemSourceのLabelをValueTextFormatDriverのTextにドライブします。
これにより、コンテキストメニューからAlbedoColorの現在値を確認出来るようになります。

![20210730164244_1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/83116/b1da456a-96b8-fa82-e3c3-9d86660c5c6b.jpeg)
ValueMultiDriver\<color>のDrivers(list)でアバターの明るさを変更したいマテリアルの数だけAddボタンを押下し、各マテリアルのColorをドライブします。

これで設定作業は終わりです。LogiXは必要ありません。

![20210730164918_1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/83116/123b3b5c-b0ed-1fd8-9dd4-78610c63c33b.jpeg)
この時手順通りに実施していくとColorの値が[0,0,0,0]で設定され真っ暗な状態になりますが、ButtonValueCycle\<color>は一度コンテキストメニューから選択されるまで値の書き換えを行わないため正常な動作です。問題ありません。

##3.動作確認
設定したアバターを着て、コンテキストメニューを開きます。

![20210730165351_1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/83116/40a576f5-d61b-f551-7838-9b92d5e564b6.jpeg)
AlbedoColorの項目が増えているので、選択します。

[0.9;0.9;0.9;1]
->[0.7;0.7;0.7;1]
->[0.5;0.5;0.5;1]
->[0.9;0.9;0.9;1]以下ループ・・・とAlbedoColorを変更出来るようになっています。

![20210730165510_1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/83116/8e99fdc2-63e3-9dcb-3d95-d91111179ac8.jpeg)

![20210730173101_1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/83116/c84c9b48-8b79-9f6d-c706-90ff2b518a74.jpeg)
NeosFesta3のテンプレートテーマ「海岸」では0.5に切り替え、同じくNeosFesta3のテンプレートテーマ「Cube」では0.9に切り替えというように使えば良いですね。

正常動作が確認できたらアバターを保存して完成です!

#おわりに
これで様々な環境光に対応出来るようになりました。
手間かもしれませんが、ワールド巡りやNeosFesta3などたくさんのワールドを読み込む場面ではきっと役に立つと思います。みんなとの記念撮影で自分だけ真っ白・真っ暗とかは避けたいですしね。

また、コンテキストメニュー項目の作成はたくさんの応用が出来ると思いますので、あなただけの便利な機能を作ってみてください。
私はDynamicBoneのOn/Offなども作成し、活用しています。
LogiXのトリガーもButtonEventに繋げますので簡単に行えます。

それでは。