個人LLMのメモ

2024年なので自分でLLMを学習させてみたい。企業が用意しているGPT-4やGeminiみたいなありあわせのものではなく、自分で好きなようにカスタマイズしてみたい。 企業と比べれば個人でできることはたかが知れているが、実際のところ本気を出したらどれくらいの性能のLLMを作成できるだろうか? モデルの大きさやデータの量よりも、データの質のほうが重要という噂もある。個人レベルでも案外良いものができるのではないか?

LLMを学習させるには

  • モデル
  • 学習データ
  • 計算機資源

の3つを揃える必要がある。また、学習スクリプトも必要だ。

モデル

公開されている様々なOSSモデルがhuggingface hubにある。pretrain済みのものを使うのがよいだろう。最初から学習させるのもやってみたいが、コスト的に厳しい。

いわゆるLocalLLMはMetaが公開しているllama2とその派生がデファクトを取っているが、llama2はライセンスが気に食わない。Mistralという企業がApachev2ライセンスのllama2互換のモデルを公開している。そして、Mistralのllama2互換モデルを日本語データで追加学習させたモデルshisaが公開されている。このshisaに追加学習してカスタマイズができるというのをひとつの目標にしたらよさそうだ。https://huggingface.co/augmxnt/shisa-7b-v1

shisaを公開しているaugmxntがどういう団体なのかはよくわからないが、akavirtualという企業から計算機資源の提供を受けたということが書いてあるので、関係する何かなのだろう。https://akavirtual.com/

学習データ

おそらく一番重要な部分で、検討が必要。とりあえずは公開されているデータでどれくらいのコストがかかるのか見積もりたい。

計算機資源

H100が使えるなら使いたい。しかしH100は500万円以上する。AWSなどのクラウドサービスを使うのも検討したが、長く何回も学習させるにはコストが高すぎる。

最新のGPUは無理、クラウドも避けたい。学習に向いた安いGPUを検討すると、現状RTX3090の中古を買うのが最も優れていそうだ。学習に最も必要なのはGPUのメモリで、RTX3090はVRAMが24GBある。ヤフオクでRTX3090の中古は10万円前後で取引されている。A100の80GBには及ばないし、3000番台で新しいGPUではないが、この価格で24GBあるのはRTX3090だけだ。同じく24GBあるRTX4090は中古でも30万円くらいする。

とりあえずRTX3090を2台揃えた。本当は4台にしたいが、マザーボードを変えなければならないので2台で様子見する。

学習スクリプト

Microsoftが公開しているOSSのDeepSpeedを使うとZeROという仕組みで少ない計算機資源で大きなモデルの学習ができる。

ZeROのアイデアは単純だ。これまで各GPUで重複してそれぞれが持っていたパラメータを代わりに分割して部分部分をそれぞれのGPUで持っておき、必要なタイミングで必要な場所に集める。これで必要なメモリ量は単純には1/(GPUの台数)倍になる。データの移動と計算をオーバーラップすることでそれらのうちの速い方にかかる時間は遅い方の時間に隠れて見えなくなる。

ZeROはstageが0, 1, 2, 3と4種類あるが、学習にかかるどのパラメータを優先順にどこまで分散するかで分かれている。僕の手元にある計算機は足りないので当然stage3を使う(つまりOptimizerのパラメータ、gradientデータ、モデルのパラメータ全部を分散して持つ)。それでも足りないので、ZeROとは別で用意されているCPU offloadingの機能も使う。これはGPUメモリの足りない分をCPUメモリで補う機能だ。

そしてCPUメモリも足りないので、NVMeストレージを買ってきてswap領域にして誤魔化している。

データの移動がボトルネックになりそうだが、こういう貧者の工夫は楽しい。

huggingfaceが公開しているtrlというOSSのexampleの学習用スクリプトを少し改造してやるとDeepSpeed ZeRO stage 3 with CPU offloadingで学習ができた。

VirtualFashionMall#3のギミックとツール周りの話

VirtualFashionMallも3回目ですね。今回もギミック制作として参加しました。今回は規模拡大に合わせてギミックだけでなくブースの配置用ツールも作りました。

これは邪教徒カルテットさんの試着自撮りです。

この記事では自分がVFM#3でやったことをくどくどと書いていきます。正直誰向けなのかと言われるとよくわからない感じになってますが、Udonギミックに興味ある方が参考にしたり、将来の自分自身が振り返ったりするときのために残しておきます。

途中で読むのが面倒になったら「最後に」まで飛んでください。

VirtualFashionMallについて知らない方はこちらの記事を先に読んでください。(VRoidFashionMallはVirtualFashionMallの前の名前です)

sandman73773941.hatenablog.com

カラーバリエーションの仕様変更

これまでのUdonWearではカラバリの切り替えは単一のマテリアルの切り替えでやっていました。これだとマテリアルが複数あったり、モデルのポリゴン形状が異なる場合に対応できないため、SkinnedMeshRendererそのものを切り替えるように変更しました。UdonHatも同様に修正しました。

もはや「カラー」バリエーションではないですね。当初は半袖長袖を切り替えるくらいを想定していたんですが、佐久本さんが男性向け服女性向け服で切り替えていてそういう使い方もあるなあと思いました。

UIの日本語対応

ミレアさん、野菜ゆうきさんからフィードバックをもらってUIがこれまで英語だけだったのを日本語バージョンも用意しました。プレイヤーが言語を選択するのは面倒くさそうなので、タイムゾーンを判別して自動で英語と日本語が切り替わるようにしました。

難しい単語を使っているわけでもないし英語だけでええやろと最初は思っていたんですが、日本語にしてみるとかなり分かりやすくなったので驚きました。UdonHatも同様に修正しました。

この説明書きはあざらしうむさんにお願いして描いてもらいました。

同期変数の修正

VRChatの仕様変更で同期変数の定義が一定数以上あると同期がされなくなるという現象が発生しました。同期変数の個数ではなく定義数が問題であるというところがミソで、最初は同期変数の数を減らすのをがんばっていたんですが、最終的に同期変数を配列にして定義数を減らすことで対応できました。

実はUdonWearはPythonコードからUdonSharpコードを生成して大量にある同期変数の同期のやりかたを一括で変えられるようにしています。コード生成は無駄に複雑さを増していてよくなかったかもと思っていましたが、結果的にはやっていて良かったです。

ちなみに同期変数を減らす過程でたまたま試着時に発生するタイムラグがなくても動くことに気づいて消しました。また服を着た後にアバターを切り替えても服が破綻しなくなりました。

設定された大きさや位置のキャッシュ化

もちおしゃ系試着ギミックの一番の弱点は試着するたびにアバターにうまく着せるには、着た後服の位置や大きさなどをユーザが設定しないといけないところです。この手間を省略できれば大きなブレイクスルーになります。

ところで話が少し逸れますが、同時期に開催されているVKet2022Summerのパラリアル大阪のBEAMSブースではキャンディちゃんさんによる試着ギミックが導入されています。ちなみにキャンディちゃんさんはVFMのきっかけとなったワールドのひとつであるColorful Magicの試着ギミックの開発者です。

vrchat.com

このキャンディちゃん式試着ギミックは大胆にも服の位置や大きさの設定が省かれていて、着た後の調整はできません。その代わり「魔法の鏡」によって服の描画順番を最後にすることでアバターが服を着ていたり胸が服から突き抜けたりしていても、鏡ごしには自然に服を着ているように見える仕組みが用意されています。

これはすごいアイデアだと思いました。特にVKetのお客さんは試着を目的にワールドに来るわけではないので、調整はむしろ野暮ったくて邪魔になります。完全に合わせようとするのはやめて、ヒトガタになるべく合うようにおおまかな自動のスケール調整と「魔法の鏡」で仕上げているのはプロの潔さを感じます。

一方で、VFMではお客さんは試着を目的で来るし、どんなアバターでも着られるようにしたい(僕自身ヒトガタから逸脱したペンギンアバターを使っている)ので、どうしても着た後の調整をやる必要があります。

調整を完全になくすことはできなくても、調整の回数を減らすことができないかと考えて、キャッシュを導入することにしました。

キャッシュは新しく服を試着したときに、最後に別の服で調整した大きさや位置を初期値として設定した状態にする機能です。この機能があれば、同じような形の服しかないような理想的な状況では最初に一度だけ調整を行えば他の服では一切調整がいらなくなります。

VRoidStudioで作成された服はだいたい同じ形をしているので理想的な状況に近いです。ただし、今回のVFMではVRoidStudioではないツールで作成された服も出展されています。そこで服ごとにキャッシュの有効無効を切り替えられるようにしてVRoidStudio製ではない服についてはキャッシュを無効にしています。

将来的にはVRoidStudio以外で一般的な服の作成ツールが出てくればキャッシュを分けるようなことも有効かもしれません。また、体格の違うアバターを頻繁に切り替えるようなユーザはあまりキャッシュの恩恵が受けられないので、アバターごとにキャッシュを分けるというのも有効かもしれません。どれくらいキャッシュが役立つか未知数だったのでとりあえず今回はシンプルなものを導入しました。うまく動いていそうなので良かったです。

同じ衣装の試着ギミックでも置かれるワールドの性格によって仕様が変わるのはおもしろいと思いました。

肩の高さ調整の無効化とスケールの調整

これまでのUdonWearでは胸部の高さ調整に伴って肩の高さも変えていました。こうするよりも肩の高さは固定にしたほうが着やすいことが分かったので無効化しました。その代わり固定だった肩のスケールを、胸部と腕のスケールに応じて変えるように変更しました。

着やすくはなったんですが、以前ひつじうたさんがやっていたような、シャツをスカートとして着こなすという荒業ができなくなってしまいました。本当は機能をON/OFFできるといいのかもしれません。

アバター身長の算出方法の修正

服の試着時に服のスケールをアバター身長に合わせて変更しています。これによって大きいアバターでも小さいアバターでも同じように服を着ることができます。身長の算出にはHips-Spine-Chestのボーンの長さを使っていました。しかしあるバージョン以降のVRMConverterForVRChatを使ってアップロードされたアバターはChestの位置がUpperChestの位置に移動してしまって、Hips-Spine-Chestの長さだとアバターの大きさが実際よりも大きく見積もられて服のスケールが大きくなってしまい、結果としてアバターが服に埋もれてしまうという現象が発生しました。(この原因究明には佐久本さんからの情報提供がめちゃくちゃ役に立ちました。ありがとうございました)

なんでVRMConverterはそんないらんことするんやと最初思いましたが、それもVRChat側の問題に対するWorkaroundのようなので仕方がなさそうです。既に大量にアップロードされているVRMConverterを使ったアバターの使用をVFM会場でやめてもらうのも現実的ではありません。VRMConverter関係なくChestがUpperChestの位置にあるようなアバターだとうまく動かないというのも変わりません。UdonWear側で対処するべき問題です。

いろいろ試行錯誤して最終的にはHips-Spine-ChestだけではなくNeckを加えてHips−Spine-Chest-Neckの長さを使うように修正しました。こうすることでChestの位置がSpineとNeckの間で動いてもトータルの長さはあまり変わらないためVRMConverterの問題を解決できました。また、体型が一般的なヒトガタから逸脱したアバターの身長もより正確に求められるようになり、より試着を安定させることができるようになりました。

デスクトッププレイヤー用ポーズシステム

5,6,7,8,9,0キーを押すとデスクトッププレイヤーもポーズが取れるシステムを作成しました。実装としてはStationをポーズごとに用意してキーが押されるとStationをプレイヤー位置に移動して座らせてアニメーションを上書きするという仕組みになっています。(Stationは位置同期しているので複数プレイヤーが同じポーズを取れないという制約があります)

前からTwitterに上げられる自撮りを見ているとVRプレイヤーはユニークなポーズが取れるのにデスクトッププレイヤーは直立したポーズしかとれなくてもったいないなと思っていました。この機能でデスクトッププレイヤーももっと試着や自撮りを楽しめるようになればいいなと思います。

ただ、現行のUdonHatとうまく動かないのが心残りです。後で修正するかもしれません。

ブース配置用ツール

今回のVFMでは出展者が増えるのに合わせて、ブース形式で展示したいという要望があったのと、毎回服やポスターをワールドに配置するのが大変なのでここらへんの作業を自動化できないかというので作りました。決まった位置にポスター画像とVRMファイルが置かれているフォルダを指定してボタンを押すとブースがシーンに配置されるようなエディタ拡張ツールにしました。

最後に

VFM#3はまだ9/3までやってます。総勢20人の出展者の皆さんが作った渾身の服とアイテム、きんととさんの企画力、渡辺秋穂さんのプロデュースノウハウ、いかめしさんのツボを押さえた会場モデリング、朝霧ルさんの適切なサポートがなければVFM#3は成立しなかったでしょう。

ひとりでも楽しめますが、ぜひ大切なフレンドと足を運んでください。あなたが試着することでVFMは完成します。

vrchat.com

OpenCVのMinGWビルド始めました

github.com

OpenCV公式ではMSVC用のライブラリは公開されていますが、MinGW用のものはありません。非公式でMinGWでビルドしたライブラリを公開している方もいますが、バージョンが少し古いです。 自分で自動的に最新のバージョンのOpenCVMinGWでビルドすることにしました。

Github Actionsを使って以下のことを自動で行います。

  • 定期的にOpenCVのrepoをチェック
  • 最新のリリースについてMinGWでビルドを実行
  • ビルドしたライブラリをリリース

ちゃんと動くかな。

self-containedな7zipのexeファイルをLinuxでXが無い環境で展開するやり方

Ubuntu20.04想定

dpkg --add-architecture i386  # wine32用
sudo apt-get -yq update
sudo apt-get -yq install wine wine32 xvfb
xvfb-run wine compressed_file.exe -y

7zipで作成されたexeファイルを展開するにはXが必要だけど無い環境ではxvfb-runを使えばよい。

UdonWearのつかいかた

UdonWearはUdonで書かれたVRChatワールド用のギミックです。 ボーンが入っている服のモデルにUdonWearを組み込むと、着られるギミックとしてワールドに置けるようになります。

sandman.booth.pm

僕がギミック担当で参加させてもらったVirtual Fashion Mallでも使用しました。その様子をききょうパンダさんが動画にまとめてくださったので、こちらを見てもらうとどういうものか分かると思います。

www.youtube.com

このドキュメントではボーンが入った服のモデルはすでに用意していると仮定して、その服のモデルにUdonWearを組み込んでワールドに置く作業を順番に説明します。

v0.10.1以前のUdonWearのドキュメントについてはこの記事ではなく、こちらの記事を参照してください。

服は持ってないけどUdonWearがどんなものかとりあえず試してみたい方は、UdonWearにはサンプルのViviClothesが入っているのでそちらを使ってください。

!!!!注意!!!!

服のモデルを組み込んだワールドをVRChatにアップロードすることはその服のモデルの利用規約に違反する場合があります。特に個人が利用するアバターに付属させた状態でアップロードすることは許可されていても、UdonWearギミックのように不特定多数のユーザーが使用できる状態でアップロードすることは禁止されている場合があります。アップロードする前に必ず利用規約を確認し、アップロード可能か不明な場合は作者さんに確認を取るなど適切な対応をしてください。

ボーンが入った服のモデルの作成方法のひとつとして、とも屋さんの羅生門ツールの下人モードを使ってVRoid Studioで作ったアバターモデルから服のモデルを取り出す方法があります。詳しくはこちらのリンクを参照してください。

tomo-shi-vi.hateblo.jp

すでに服のモデルのプレハブを持っていて、それを使いたい方は、ボーンのルートがヒエラルキーの一番上の親になっておらず、一番上の親のひとつ下の子になっていることを確認してください。もしそうなっていなければ、そうなるように修正してください。

OKな例。ボーンのルートであるRootが一番の上の親であるViviClothesのひとつ下の子になっている。

ダメな例。ボーンのルートであるRootが一番上の親になってしまっている。

また、服のモデルはT字ポーズになっている必要があります。T字ポーズになっていない場合は修正してください。

OKな例。T字ポーズになっている。

誤った例。T字ポーズになっていない。

服のボーンの回転によってはUdonWearがうまく組み込めない場合があります。可能であれば、T字ポーズにさせたときに各ボーンの回転がidentityになるようにしてください。

UdonWearを組み込む

VRChat SDK3(アバター用のものではなく、ワールド用のもの)とUdonSharpがインポート済みのUnityのプロジェクトを用意します。

UdonSharpはこちらのリンクから最新のリリース(Pre releaseではなくLatest releaseです)をダウンロードしてください。

github.com

なお、VRChat SDK3をインポートしてからUdonSharpをインポートするように注意してください。

Unityプロジェクトを開いて、Assets ー> Import Package -> Custom PackageでUdonWearのパッケージをインポートします。

インポートが終わったら、Window -> UdonWear Editorを選択してUdonWearのエディタウィンドウを開きます。

UdonWearのエディタウィンドウを開いた直後の状態

Create New Settingsを押してUdonWearの設定を保存するSettingsファイルを作成します。衣装ごとにSettingsファイルを分けておくと、後でSettingsを指定することで衣装ごとに一括で設定を読み込むことができます。

Settingsファイルは適当な場所に保存してください。Settingsファイルを作成すると、UdonWearエディターウィンドウのSettingsに自動でそのファイルがセットされます。

UdonWearEditorSettingsを作成した後の状態

いきなりエラーが出ていますが、これは服のモデルをまだ指定していないからです。服のモデルのプレハブをTarget Clothesにドラッグドロップします。(服のモデルを用意していない場合は、Sampleディレクトリにお試し用の服モデル「ViviClothes」を置いてあるのでそちらを使ってください)

TargetClothesを指定した状態

まだエラーが出ていますが、これはボーンの対応付けを設定していないからです。Auto Find Clothes Bone Transform Namesボタンを押してください。このボタンを押すことで自動でボーンの対応付けを行います。ここで対応付けがうまくいかない場合は「服がうまくアバターに追従してくれない場合」を参照してください。

そうするとエラーが消えて各種項目が表示され、Create Instanceボタンが押せるようになります。

Auto Find Clothes Bone Transform Namesボタンを押した後

Create Instanceボタンを押して、シーンにUdonWearが組み込まれた服のギミックを置きます。この時、ヒエラルキー内のTransformを選択しておくと、そのTransformの場所にそのTransformの子要素として置きます。選択しなかった場合はSceneの原点に置きます。

出したい場所のTransformを指定する

Create Instanceボタンを押すとシーンにUdonWearが組み込まれた服が置かれる

VRChatSDKのWindowでBuild & Testを押して動作確認します。服がうまくアバターに追従していれば完了です。

服がうまくアバターに追従してくれない場合

服モデルをアバターに追従させるためには、服モデルに設定されている各関節ボーンそれぞれについて対応するギミックの関節ボーンを対応付ける必要があります。UdonWearのエディタがある程度自動でこの対応付けを設定するようになっていますが、服の関節ボーンに付いている名前によってはうまくいかない場合があります。うまくいかない場合は、手作業で対応付けする必要があります。

ここではCC0で公開されているP StoreのPOPPOさんP_Store_series_12を使って説明します。緩いライセンスで素晴らしい服のモデルを公開してくださっているPOPPOさんに感謝します。

腕のボーンが正しく追従していない例

腕のボーン(LeftUpperArm、LeftLowerArm、RightUpperArm、RightLowerArm)が正しく設定されていない

服のプレハブを開き、Hierarchyウィンドウから追従させたい服の関節ボーンを対応するUdonWearEditor上のフィールドにドラッグドロップすると設定できます。

服のプレハブを開いて関節ボーンの設定をする(Left arm、Left elbow、Right arm、Right elbowがUdonWearEditorで設定されていない)

設定された状態

他にも設定されていないボーンがありますが、服モデルにそもそも存在しないボーンや追従させる必要のないボーンは設定する必要はありません。

正しく追従するようになった状態

カラーバリエーション設定

UdonWearには服のカラーバリエーションを切り替える機能があります。

TargetClothes 1, Target Clothes 2に切り替えたい服を設定してください。

UdonWearのオプション設定

UdonWearのエディタウィンドウにはTarget Clothes以外にもオプションがあります。

音声とその他のオプション

Advanced mode is default

ここにチェックをつけると、調整パネルでAdvancedにチェックが付いた状態をデフォルトにします。

DetachRefHeightOffset

VRモードで脱ぐときに両トリガーを押す基準位置の高さを設定します。0でプレイヤーの頭の位置の高さと等しくなります。デフォルトは-0.4で、肩辺りの高さが基準になるようにしています。これでT字ポーズの状態で両トリガーを押すと脱ぐという操作になります。

ClothesName

調整パネルに表示される服の名前を設定します。デフォルトではTargetClothesの名前が設定されます。

Attach Sound

服を着たとき(=服ギミックをアバターに取り付けたとき)の効果音を設定します。

Detach Sound

服を脱いだとき(=服ギミックをアバターから取り外したとき)の効果音を設定します。

Reset Sound

調整した値をリセットしたときの効果音を設定します。

ChangeMaterial Sound

マテリアルを切り替えたときの効果音を設定します。

Close Sound

調整パネルを閉じたときの効果音を設定します。

Proxymity

服ギミックのコライダーにインタラクトできる距離を設定します。

ResetTransformThreshold

UdonWearはある服ギミックを最後に触ったプレイヤーがその服ギミックから一定時間離れた状態で一定時間が経過すると服ギミックのTransformをリセットします。この項目ではその設定を行います。

Distance

ここで設定した距離以上離れると時間のカウントを開始します。

Sec

リセットされるまでの秒数を設定します。

CloseEditorPanelDistance

ここで設定した距離以上プレイヤーが調整パネルから離れるとUdonWearは調整パネルを閉じます。

ArmAngle

ここで設定した角度でUdonWearが服のポーズの初期化時にUpperArmボーンを回転させます。特にこの値が70度くらいに設定すると服は着られていないときにA字ポーズの状態になります。この値を0に設定すると服がT字ポーズの状態になります。この値を変えてもScene上では服はT字ポーズで置かれることに注意してください。UdonWearが実行時に設定された角度分回転させます。

その他のおまけ

UdonWearパッケージにはいくつかのおまけが付属しています。必要に応じて活用してください。

ギミックの説明用ポスター

UdonWearギミックの説明用ポスターです。UdonWear/Prefabs/InstructionTextures にあります。どれもライセンスはCC0です。これらは東京アザラシセンターのあざらしうむさんが作成してくれました。感謝します。

試着室のモデル

シンプルな試着室のモデルです。このモデルのライセンスはCC0です。これもあざらしうむさんが作成してくれました。大変感謝します。

UdonWear用の拡張メニュー

プレハブはUdonWear/Prefabs/UdonWearExtraMenu.prefab です。

VRChatのメニュー呼び出しで一緒に表示されるUdonWear用の拡張メニューです。Detachのやりかたの説明とDetachボタンが付属しています。

位置はどこでもいいのでSceneの中に置いてください。 Sceneに置いたUdonWearExtraMenuのUdonBehaviourコンポーネントのUdonWearRootTransformに、UdonWearの入った服(画像中ではViviClothes)を子要素以下の要素(つまり孫要素やひ孫要素でもOK)として含むTransform(画像中ではUdonWearRoot)を指定してください。含まれているUdonWearについてDetachボタンでDetachできるようになります。

EmergencyDetachButton

プレハブはUdonWear/Prefabs/EmergencyDetachButton.prefab です。 Interactすることで服をDetachできるボタンです。UdonWear用の拡張メニューと同様に、UdonBehaviourコンポーネントのUdonWearRootTransformに、UdonWearの入った服(画像中ではViviClothes)を子要素以下の要素(つまり孫要素やひ孫要素でもOK)として含むTransform(画像中ではUdonWearRoot)を指定してください。含まれているUdonWearについてこのボタンをInteractすることでDetachできるようになります。

調整パネルの日本語/英語切り替えシステム

プレハブはUdonWear/Prefabs/UdonWearLanguageSelector.prefab です。

調整パネルの言語はデフォルトでは英語ですが、このプレハブをSceneに置くことでプレイヤーのタイムゾーンに応じて日本語と英語を自動で切り替えるようになります。

位置はどこでもいいのでSceneの中に置くだけで有効になります。

服のスケールと位置のキャッシュシステム

プレハブはUdonWear/Prefabs/UdonWearOffsetCache.prefab です。

プレイヤーが着た後服のスケールや位置を調整する手間を減らすための機能です。プレイヤーがまだ一度も着たことのない服を着た場合に、最後に着た別の服で調整したスケールや位置をデフォルトの値として設定します。

位置はどこでもいいのでSceneの中に置くだけで有効になります。

服によってはキャッシュを無効にしたいことがあるかもしれません。その場合はCreateして出したUdonWearのオブジェクトのUdonBehaviourコンポーネントの「IsOffsetCacheEnabledIfAvailable」のチェックを外してください。

速習VRChatギミッカーのためのUnityEditor拡張

ユーザーがカスタマイズできるようなちょっと複雑なギミックを配布しようとするとPrefabをぽんと置くだけではセットアップできなくて困ることがよくあります。そんなときはUnityEditor拡張の出番です。UnityEditor拡張というと初めて使う人には何か難しそうなものに思えますが、実際には全然難しくないし、これほど便利なものはありません。UnityEditor拡張と一緒にギミックを配布すればユーザーはPrefabをぽんと置くのと同じか、それよりももっと簡単にギミックをセットアップできるようになります。やっていきましょう。

まずはEditorというディレクトリを作成してください。場所はどこでもかまいませんが、ギミックを配布しようとしているなら、そのギミックをパッケージにするときのRootのディレクトリがあるでしょうからその直下に作るのが良いでしょう。

f:id:sandman73773941:20210825000127p:plain

C#ソースファイルを作成します。

f:id:sandman73773941:20210825000158p:plain

using UnityEngine;
using UnityEditor;

class MyEditor : EditorWindow {
    [MenuItem("Window/My Window")]
    static void Init()
    {
        EditorWindow.GetWindow(typeof(MyEditor));
    }

    private void OnGUI()
    {
    }
};

これだけでWindowメニューにMyWindowという項目が表示されて、それを選択すると何もないWindowが出てきます。簡単ですね。

f:id:sandman73773941:20210825000238p:plain

f:id:sandman73773941:20210825000512p:plain

このままだと殺風景なので何か適当にGameObjectを受け取れるようにしましょう。

using UnityEngine;
using UnityEditor;

class MyEditor : EditorWindow
{
    public GameObject someObject; // <- 追加

    [MenuItem("Window/My Window")]
    static void Init()
    {
        EditorWindow.GetWindow(typeof(MyEditor));
    }

    private void OnGUI()
    {
        someObject = (GameObject)EditorGUILayout.ObjectField("SomeObject", someObject, typeof(GameObject), false); // <- 追加
    }
};

EditorGUILayout.ObjectFieldはObjectを取るフィールドを作成する関数ですが、floatを取りたいときはFloatField、stringを取りたいときはTextFieldが用意されています。

試しにCreateボタンを押したらSomeObjectのコピーをSceneに配置するようにしましょう。ボタンも簡単に追加できます。

using UnityEngine;
using UnityEditor;

class MyEditor : EditorWindow
{
    public GameObject someObject;
    public float floatValue = 3.14f;
    public string stringValue = "this is default value";

    [MenuItem("Window/My Window")]
    static void Init()
    {
        EditorWindow.GetWindow(typeof(MyEditor));
    }

    private void OnGUI()
    {
        someObject = (GameObject)EditorGUILayout.ObjectField("MySomeObject", someObject, typeof(GameObject), true);
        floatValue = EditorGUILayout.FloatField("MyFloatValue", floatValue);
        stringValue = EditorGUILayout.TextField("MyStringValue", stringValue);

        if (GUILayout.Button("Create")) // <- Createボタンを追加
        {
            GameObject createdObject = GameObject.Instantiate(someObject); // <- オブジェクトをコピーしてSceneに配置する
            createdObject.name = stringValue + floatValue.ToString(); // Fieldの値を元に名前を設定する
        }
    }
};

f:id:sandman73773941:20210825000341p:plain

これだけでかなりのことができるようになると思います。ボタン以外にも様々なUIコンポーネントが用意されているので探してみてください。

Fieldを増やしていくと入力した値がUnityを再起動するとリセットされるのが気になってきます。そういうときはScriptableObjectの出番です。

ScriptableObjectについてはそのうち追記するかも。

UdonHatのつかいかた

UdonHatはUdonで書かれたVRChatワールド用のギミックです。 帽子や眼鏡、髪飾りなどの頭部に着けるアクセサリーのモデルにUdonHatを組み込むと、着られるギミックとしてワールドに置けるようになります。

sandman.booth.pm

ざらしうむさんの夏物帽子やアクセサリーを試着できるワールド「UdonHat,SUMMER」や、きんととさんの「VRoidのお話まったりしよう会」の会場ワールドで使ってもらいました。

このドキュメントでは帽子のモデルはすでに用意していると仮定して、その帽子のモデルにUdonHatを組み込んでワールドに置く作業を順番に説明します。

帽子は持ってないけどUdonHatがどんなものかとりあえず試してみたい方は、UdonHatにはサンプルの帽子のモデルがUdonHat/Sampleに入っているのでそちらを使ってください。このモデルはP_StoreのPoppoさんがCC0で公開しているモデルを元にしています。

booth.pm

!!!!注意!!!!

帽子のモデルを組み込んだワールドをVRChatにアップロードすることはその帽子のモデルの利用規約に違反する場合があります。特に個人が利用するアバターに付属させた状態でアップロードすることは許可されていても、UdonHatギミックのように不特定多数のユーザーが使用できる状態でアップロードすることは禁止されている場合があります。アップロードする前に必ず利用規約を確認し、アップロード可能か不明な場合は作者さんに確認を取るなど適切な対応をしてください。

UdonHatを組み込む

VRChat SDK3(アバター用のものではなく、ワールド用のもの)とUdonSharpがインポート済みのUnityのプロジェクトを用意します。

UdonSharpはこちらのリンクから最新のリリース(Pre releaseではなくLatest releaseです)をダウンロードしてください。

github.com

なお、VRChat SDK3をインポートしてからUdonSharpをインポートするように注意してください。

Unityプロジェクトを開いて、Assets ー> Import Package -> Custom PackageでUdonHatのパッケージをインポートします。

インポートが終わったら、Window -> UdonHat Editorを選択してUdonHatのエディタウィンドウを開きます。

f:id:sandman73773941:20210623183148p:plain

Create New Settingsを押してUdonHatの設定を保存するSettingsファイルを作成します。帽子ごとにSettingsファイルを分けておくと、後でSettingsを指定することで帽子ごとに一括で設定を読み込むことができます。

f:id:sandman73773941:20210623183209p:plain

f:id:sandman73773941:20210623183236p:plain

Settingsファイルを作成すると、Settingsに自動でそのファイルがセットされます。

f:id:sandman73773941:20210623183253p:plain

いきなりエラーが出ていますが、これは帽子のモデルをまだ指定していないからです。帽子のモデルのプレハブをTarget Hatにドラッグドロップします。(帽子のモデルを用意していない場合は、Sampleディレクトリにお試し用の帽子モデルを置いてあるのでそちらを使ってください)

そうするとエラーが消えて各種項目が表示され、Create New Instanceボタンが押せるようになります。

f:id:sandman73773941:20210623183316p:plain

Create New Instanceボタンを押して、シーンにUdonHatが組み込まれた帽子のギミックを置きます。この時、ヒエラルキー内のTransformを選択しておくと、そのTransformの場所にそのTransformの子要素として置きます。選択しなかった場合はSceneの原点に置きます。

f:id:sandman73773941:20210623183344p:plain

f:id:sandman73773941:20210623183359p:plain

VRChatSDKのWindowでBuild & Testを押して動作確認します。帽子をピックアップして使用すると帽子がアバターの頭部に固定されて、帽子がうまくアバターに追従していれば完了です。

UdonHatのマテリアル設定

UdonHatには帽子のマテリアルを切り替える機能があります。この機能を使っていわゆる帽子のカラバリを設定できます。UdonHatEditorのMaterials以下の項目でこの設定を行います。 現状、切り替えられるマテリアルはひとつです。

設定する手順は以下のとおりです。

  1. Target Mesh Renderer Nameで切り替えたいマテリアルを使用しているMeshRendererの名前を指定してください。

  2. Target Material Indexで切り替えたいマテリアルを指定してください。

  3. Material Numで切り替えられるマテリアルの種類の数を設定します。デフォルトは3に設定しています。

  4. Initial Material Indexでどのマテリアルを最初に使用するかを指定します。

  5. 切り替える別のマテリアルをmaterials[1]やmaterials[2]にドラッグドロップしてください。なお、material[0]は帽子のプレハブで設定されているマテリアルが自動で設定されます。設定されていないマテリアルは単に無視されます。

これでCreateすると調整パネルの右上のMaterialボタンでマテリアルを切り替えられるようになります。

UdonHatのオプション設定

UdonHatのエディタウィンドウにはTarget Hat以外にもオプションがあります。

Hat Name

調整パネルに表示される帽子の名前を設定します。デフォルトではTarget Hatの名前が設定されます。

Attach Sound

帽子を着たとき(=帽子ギミックをアバターに取り付けたとき)の効果音を設定します。

Detach Sound

帽子を脱いだとき(=帽子ギミックをアバターから取り外したとき)の効果音を設定します。

Reset Sound

調整した値をリセットしたときの効果音を設定します。

ChangeMaterial Sound

マテリアルを切り替えたときの効果音を設定します。

Close Sound

調整パネルを閉じたときの効果音を設定します。

Proxymity

帽子ギミックのコライダーにインタラクトできる距離を設定します。

ResetTransformThreshold

UdonHatはある帽子ギミックを最後に触ったプレイヤーがその帽子ギミックから一定時間離れた状態で一定時間が経過すると帽子ギミックのTransformをリセットします。この項目ではその設定を行います。

Distance

ここで設定した距離以上離れると時間のカウントを開始します。

Sec

リセットされるまでの秒数を設定します。

CloseEditorPanelDistance

ここで設定した距離以上プレイヤーが調整パネルから離れると調整パネルを閉じます。

その他のおまけ

UdonHatパッケージにはいくつかのおまけが付属しています。必要に応じて活用してください。

ギミックの説明用ポスター

f:id:sandman73773941:20210623183437p:plain

f:id:sandman73773941:20210623183453p:plain

UdonHatギミックの説明用ポスターです。UdonHat/Prefabs/Textures にあります。AttachとDetachのためのポスターがあります。どちらもライセンスはCC0です。これらは東京アザラシセンターのあざらしうむさんが作成してくれました。感謝します。

UdonHat用の拡張メニュー

f:id:sandman73773941:20210623183710p:plain

プレハブはUdonHat/Prefabs/UdonHatExtraMenu.prefab です。 VRChatのメニュー呼び出しで一緒に表示されるUdonHat用の拡張メニューです。Detachのやりかたの説明とDetachボタンが付属しています。

位置はどこでもいいのでSceneの中に置いてください。 Sceneに置いたUdonHatExtraMenuのUdonBehaviourコンポーネントのUdonHatRootTransformに、UdonHatの入った帽子を子要素以下の要素(つまり孫要素やひ孫要素でもOK)として含むTransformを指定してください。含まれているUdonHatについてDetachボタンでDetachできるようになります。

EmergencyDetachButton

f:id:sandman73773941:20210623183739p:plain

プレハブはUdonHat/Prefabs/EmergencyDetachButton.prefab です。 Interactすることで帽子をDetachできるボタンです。UdonHat用の拡張メニューと同様に、UdonBehaviourコンポーネントのUdonHatRootTransformに対象のUdonHat帽子ギミックを含むTransformを設定してください。