見出し画像

3step+αで作る光源ライト(vcrhatアバター, MA使用)

※コンテンツ部分はすべて無料で最後まで読めます。


はじめに

先日以下の製品をboothで出品しました。

今回はこのギミックの内部実装についての記事となります。
3stepで作る簡易版は約1500文字、+αを含めた全体像は約7500文字となります。(「1500文字+7500文字とか読む気しねえよ」という人は↑を購入いただくとこの記事の内容がすべて実現できます。(マ))

対象読者

・vrchatをプレイしていて、ある程度アバター改変を行う知識・環境がある
・ライトギミックの内部実装に興味がある

3stepで作る光源ライト

大言壮語なタイトルにしていますが機能の根幹をなすライト部分は本当に簡単に実装できます。
ここではアバターに光源ライトを組み込み、ライトオンオフのExメニューを設定して、Exメニューからライトをオンオフする。というところまでを以下の3stepで作ります。

  1. ライトコンポーネントをつける

  2. ライト位置調整

  3. AvatarMenuCreator for MAでExメニュー設定

ライトギミックを実装したいアバターはunity上で開いておいてください。
それとModularAvatarAvatarMenuCreator for MAを使うので導入は済ませておいてください。(step 0)

今回もサンプルとしてシアンちゃんを使います

step 1 ライトコンポーネントをつける

ヒエラルキー上でアバタールートを右クリック→空のオブジェクトを作成を選択して空のオブジェクトを作ります。名前はLightにします。

空オブジェクト作っただけ

コンポーネントを追加からLightを選択します。
パラメータがいろいろありますが今回はタイプはポイントで、範囲、色、強さはお好みで設定します。
例では範囲50、色は白、強さは3としています。(そこそこ強めの光源を想定)

範囲、色、強さを設定

また、ライトを追加するとシーン上に電球マークが表示されることも確認してください。表示されない場合は右上のギズモの表示をオンにしてください。

シーン上でもライトが追加されたことが分かる

この時点でシーンをよく見ると、アバターが照らされていることが分かります。(強さの数値を大きくして、顔や服付近に持ってくると分かりやすい)

step 2 ライト位置調整

光源の中心となる位置を決めます。今回は右手の手のひらの上に光源を出すことを考えます。右手に追従してほしいのでコンポーネントを追加からMA Bone Proxyを追加します。

右手(の中指の関節)ボーンに紐づける

配置モードを一度「子として・ルートに配置」に変更に変更するとTransformに対象ボーンと同じ座標が代入されるので、そこから位置調整するのが良いと思います。「子として・ワールド位置と向きを維持」に変更してから位置を調整してください。

右手付近に移動

step 3 AvatarMenuCreator for MAでExメニュー設定

コンポーネントを追加からAvatar Toggle Menu Creatorを追加します。(AvatarMenuCreator for MAの使い方の項目にある「Tools」→「Modular Avatar」→「AvatarMenuCreater for Modular Avatar」から進めても問題ありません。)

オブジェクトを追加からLightオブジェクトを追加し、ON=表示にします。ついでにお好みでそれっぽい画像を用意してアイコンに設定します。

Exメニュー設定

設定したらMA Menu installerを追加を押します。(既にMA Menu installerがついている場合は必要ないです。)

動作確認

以上で作業は終了です。
最終的にLightオブジェクトに

  • Transform(配置したい場所の座標が代入されている)

  • Light

  • MA Bone Proxy

  • Avatar Toggle Menu Creator

  • MA Menu installer

がついていればOKです。

プレイモードで確認してみましょう。
まずGestureManagerでExメニューを確認すると、メニューが追加されています。

追加されたLightメニュー

そしてこのメニューをオンオフするとライトがオンオフします。

ライトオフ
ライトオン

問題なさそうならアバターアップロードしてvrchat内で確認してみてください。
以上でライトの実装は完了となります。

お疲れさまでした。
これで暗いワールドやホラーワールドも怖くないですね!(※ワールドの光源設定が変更されていて、アバター組み込みのライトが無効化されている場合もあるため、どのワールドでも機能するというわけではありません。)

はい。ここまでで「とりあえず暗いワールドを照らしたいんだけど」という需要に対して一応使えるものをサクッと作りました。ここからは+αです。

以下で販売しているギミックに実装されている機能をもう少し見ていきます。

機能
・ガラス球オンオフ
  中心の確認用ガラス球モデルの表示をオンオフします。
  ライトオンオフには影響しません。
・ライトオンオフ
  ライトがオンオフできます。
・ローカル化
  光源効果を自分だけに適用します。
・強度調整
  無段階調整メニューにて設定可能(弱~強)
・色相調整
  無段階調整メニューにて設定可能(白, 赤←色相変化→紫)

ここまでで「ライトオンオフ」は作成しましたが、他の機能も実装するとなるともう少し構造を考える必要があります。(※「ガラス球オンオフ」についてはこの記事では触れません(ガワの話なので))。
以下からこれらの機能がどう作られているか解説していきます。

prefab構造について

光源ライトギミックのprefabを見ると、以下の構造になっています。

prefabとAssets構造

Assetsのディレクトリ構成については販売ページにあるので合わせて確認ください(マ)。

Lightオブジェクトの配下にGlassSphere(ガラス球モデル)とPointLightオブジェクトがあります。正直構造はいろいろ模索中なのですが、重要なことはこの後作成するアニメーションファイルは、ヒエラルキー上の構造をもとに対象を探索するので途中で構造を変更すると面倒なことになります。なりました。
(余談:prefab直下のオブジェクトのTransformは原点にするのがマナーが良いらしい。Bone Proxyで動かすものも階層を深くして、prefab全体を動かさない方が良い?)

今回はLightオブジェクトにMA関連のコンポーネントを付与し、PointLightオブジェクトにはLightコンポーネントのみ付与します。

まず上画像のように空のオブジェクトとしてLightオブジェクトを作り、その配下にPointLightオブジェクトを作ります。3stepで作成したコンポーネントについて、

  • Transform→Lightオブジェクトの座標に採用、PointLightはすべて0

  • Light→PointLightオブジェクトに付与

  • MA Bone Proxy→Lightオブジェクトに付与

  • Avatar Toggle Menu Creator→削除

  • MA Menu installer→Lightオブジェクトに付与

と移動させます。コンポーネントのコピーや値のコピペを活用すると楽にできるかと思います。

それとAssetsの方で、これから作成するものを置いておくディレクトリをテキトーに作っておきます。こちらのパスは融通が効くので分かる場所ならどこでもいいです。以後、このディレクトリをワークディレクトリと呼びます。

Animator作成(ローカル化について)

ワークディレクトリで右クリック→作成→アニメーターコントローラーから空のAnimatorを作ります。名前はPointLightとします。(オブジェクト名と紛らわしいですがアイコンと拡張子で判別できます。)
アニメータータブのパラメータータブを選択し、画像のようにパラメータを作成します。

使用パラメータ一覧
  • light_state: bool型、ライトオンオフを制御するための変数

  • light_color: float型、ライトの色を制御するための変数

  • light_intensity: float型、ライトの強さを制御するための変数

  • light_is_local: bool型、ローカル化の機能を制御するための変数

  • IsLocal: bool型、vrcsdk組み込みの変数、ローカル化に関係する

大文字小文字は区別されるので注意してください。(小文字のエルと大文字のアイにも注意)

次にレイヤータブに移り、ステートマシンのガワだけ作成します。(アニメーションファイルをまだ作っていないので各ステートに割り当てるべきアニメーションファイルが存在しないため。)
LightOnOffレイヤーとLightColorレイヤーを新規作成し、どちらも歯車ボタンからウェイトを1にしてください。

LightOnOffレイヤー
LightColorレイヤー

各ステートは画像の通り作りますが、アニメーションファイルはまだ作っていないので、今のところはMotionの欄はすべて空白で問題ありません。
トランザクション(矢印)についてはパラメーターを定義しているので作成できます。以下のように設定してください。番号は画像中の番号と対応します。

・トランザクション1~5共通
 終了時間ありのチェックを外す
 遷移間隔と遷移オフセットを0に
 自身に遷移のチェックを外す

1~5共通設定

・トランザクション1
 2本矢印が引かれている(or条件
 Conditionsについて
  1本目の矢印:light_is_local が true かつ IsLocal が false
  2本目の矢印:light_state が false

・トランザクション2
 Conditionsについて:
  light_state が true かつ light_is_local が false

・トランザクション3
 Conditionsについて:
  light_state が true かつ light_is_local が true かつ IsLocal が true

・トランザクション4
 Conditionsについて:
  light_state が true

・トランザクション5
 Conditionsについて:
  light_state が true かつ IsLocal が true

何をやっているのかという感じですが、動きを書き下すと、まずEntryから入ってきてデフォルトはLightOff(ライトオフ)です。
そこからオンオフを司る light_state が trueなら左下のLightOn(ライトオン)になります。
ローカル化の機能を実現するためにvrcsdk組み込みのIsLocalと自前のローカル化有効フラグlight_is_localで挙動を制御しています。特徴的なのはトランザクション1の条件の一つである「light_is_local が true かつ IsLocal が false」で、これを書き下すと「ライトのローカル化の設定が有効の場合、自分以外のプレイヤーはこの矢印の先(LightOff)に遷移する。」という挙動になり、結果としてローカル化の設定を有効にすると、ライトをオンにしても自分以外のプレイヤーはライトオフになります。

このあたりの挙動についてはIsLocalやAny Stateについて調べていただければと。複雑なので解説は丸投げします。
(余談:たぶんステートマシンはもっと簡潔に作ることができる)

Animation作成1(ライト強度)

では(めんどくさい)アニメーションファイルを作っていくのですが、その前にMA回りの設定をすると少し楽ができるのでやっておきます。
以下のようにLightオブジェクトに MA Merge Animator と (unity純正の)AnimatorMA Parameters コンポーネントを追加します。

コンポーネント追加

まずMA Merge Animatorに先ほどガワを作成したPointLightアニメーターを設定します。設定値は画像の通りですが重要なのは付属アニメーターを削除
にチェックを入れることです。
次にAnimatorコンポーネントにもPointLightアニメーターを設定します。これはアニメーションファイルを円滑に作成するためだけに存在するので、アバタービルド時には消えてほしいものになります。そのための設定が先の付属アニメーターを削除なわけです。
最後にMA Parametersですが、追加時点ではここには何もないと思いますが、未登録パラメーターを展開するとPointLightアニメーターで定義した変数が出てきます。それらをすべて登録するのですが、登録後にそれぞれの変数を展開してパラメーター型アニメーターで定義したものと同じものを設定してください。

MA Parameters定義 すべての変数について確認する
ついでに自動リネームにチェックもつけておく

さて、これでアニメーションファイルを作る準備ができました。作っていきましょう。
アニメーションタブが開かれていない場合は上のツールバーからウィンドウ→アニメーション→アニメーションでタブを開いておきます。そしてLightオブジェクトを選択してからアニメーションタブのプルダウン→新しいクリップの作成を選択します。

画像ではプルダウンに作成済みのアニメーションファイルがありますが、
初回は「新しいクリップを作成」のみのはずなのでそのまま気にせず進めてください。

作るアニメーションは以下の3つです。

  • ライトをオンにする(強度も加味する)アニメーション「LightOn

  • ライトをオフにするアニメーション「LightOff

  • ライトの色を変えるアニメーション「LightColor

まずLightOnから作ります。新しいクリップを作成からワークディレクトリにLightOnアニメーションを作成します。その後、記録ボタンを押してライトのIs_ActiveとIntensityとRangeのプロパティを追加します。

Is_ActiveとIntensityとRange
プロパティを追加からでももちろんOK
記録ボタンを押した後に操作すべき箇所

フレーム0地点で、Is_Activeがtrue, Intensityが0.1, Rangeが30とします(ライト強度が弱い状態を表現)。
続いてフレーム10地点にキーを追加し、Is_Activeがtrue, Intensityが3, Rangeが50と設定します(ライト強度が強い状態を表現)。

キー追加時は赤枠の場所を右クリックして追加

後ほどlight_intensity変数を使って割合でこの範囲の値をとることになります。オン状態での強度の最低値と最大値を定めたと考えてください。

ライトオフの方は簡単で、すべてゼロにするだけです。(Is_Activeのみfalseにすれば事足りるが一応すべてゼロにしておく。)
新しいクリップを作成からワークディレクトリにLightOffアニメーションを作成。

ライトオフはすべて0でOK

こちらは特に変化しないのでフレーム0にのみキーがあれば十分です。

Animation作成2(色相変更)

さて、これで残るは "ライトの色を変えるアニメーション「LightColor」" だけです。強度と同じようにプロパティを見てみましょう。
新しいクリップを作成からワークディレクトリにLightColorアニメーションを作成。録画ボタンを押してからライトの色をいじってみます。このとき色の指定方式をHSVに設定して、H, S, V, Aすべて動かしてください。

HSVとA

すると以下のようにプロパティが追加されます。

色相変更アニメーション フレーム0

色はColorのrgbとa(アルファブレンド)で表現されるようです。このうちaは1で固定で良いです。rgbを変化させれば色相が変わります。先程のHSVを動かしたときにSを100にするとカラーサークルの原色の色になります。

H=0,そのほかは100

この状態でHを0~360にするとカラーサークル上で変化する色に対応することが分かります。しかしアニメーションプロパティはrgbなのでこのまま0~360に対応させることはできません。そこで総フレーム数を100と定めて、360と100の公約数だけキーを打ちます。今回は10段階のキーを作成します。このあたりの方法は以下サイトの「色変更のアニメーション」の手法を参考にしています。

ただし白を例外として入れる必要があるため、フレーム0は白、フレーム1は赤(H=0)~フレーム100は赤(H=360)とします。
記録ボタンを押し、フレーム数選択→キーを追加→色を操作してHSVを所定の値にする。を繰り返します。

フレーム0は白
フレーム1は赤(H=0)
フレーム100は赤(H=360は実質H=0と同じ)
フレーム50は水色(H=180)
フレーム10刻みにキーを打ち、
H=(360/100)*[1~10段階]の色を記録・設定

このとき注意すべき点としてH以外のSVとAの値はどのキーでも常に100として設定してください(白以外)。

Animator設定(アニメーション割り当て)

アニメーションファイルは用意できましたか?Animatorタブに戻って各ステートにアニメーションファイルを割り当てます。
まずステートマシン上に追加した覚えのないステートは削除してください。(アニメーション新規作成時に自動的に作られる?)

LightOnOffレイヤー

全ステートに共通ですが、Write Defaultsのチェックは外してください。
LightOffステートのMotionに、ライトをオフにするアニメーション「LightOff」を割り当てます。

LightOffステート

続いてLightOn_***ステート3つすべてのMotionに、ライトをオンにするアニメーション「LightOn」を割り当てます。その後Motion Timeのパラメータにチェックを入れ、light_intensityを指定します(3つとも)。

LightOn系ステートはMotion Timeにlight_intensityを設定

最後にLightColorレイヤーに移り、LightColorステートのMotionに、ライトの色を変えるアニメーション「LightColor」を割り当てます。その後Motion Timeのパラメータにチェックを入れ、light_colorを指定します。

LightColorレイヤー
LightColorステートはMotion Timeにlight_colorを設定

以上でAnimatorとアニメーション関連の設定は完了です。お疲れさまでした。

Exメニュー作成

アニメーション関連が終われば後はほぼウィニングランです。頑張っていきましょう。
久しぶりにAssetsに戻って、ワークディレクトリで右クリック→作成→VRChat→Avatars→Expressions Menuを選択して、二つ、空のメニューを作ります。名前はLightMenuLightSubMenuとします。

(余談:Exメニュー作成方法について
 「あれ?ExメニューはMAでヒエラルキー上でつくれるよね?」と思った方。正解です。
 ただ今回はMAでなくvrcsdk純正のメニューを作ります。製品としてまとめる際にメニューファイルで管理した方が取り回しが良いので。)

まずLightMenuですが、一つだけ項目を追加し、タイプをサブメニューとしてLightSubMenuを指定します。名前、アイコンをそれっぽくお好みで設定します。

LightMenu

次にLightSubMenuですが、こちらはそれぞれの機能に対応する項目を4つ追加します。

  • ライトオンオフ, Toggleタイプ, light_state

  • ローカル化, Toggleタイプ, light_is_local

  • 明るさ調整, RadialPuppetタイプ, Rotationにlight_intensity

  • 色相調整, RadialPuppetタイプ, Rotationにlight_color

ライトオンオフ
ローカル化
明るさ調整
色相調整

それぞれ名前とアイコンはそれっぽいものでOKです。注意点としては変数名のガイドはないため大文字小文字を間違えないことと、RadialPuppetの場合はRotationの方に変数名を入力することです。何やらパラメータがないと警告が出ていますが、パラメータは実行時にMA Parametersで定義されるため、ビルド前はこの警告が出てても大丈夫です。Animatorやらなんやらで散々準備してきた布石はここから回収されます。

以上の設定ができたら、ヒエラルキー上のLightオブジェクトにMA Menu Installerをつけます。
プレハブ開発者向け設定を展開し、インストールされるメニューにLightMenuを設定します。

インストールされるメニューにLightMenuを設定

以上で作業は終了です。お疲れさまでした!

動作確認

プレイモードで確認してみましょう。
まずGestureManagerでExメニューを確認すると、メニューが追加されています。

Exメニューがサブメニューで階層になっている

シーンを見ると電球マークがないためデフォルトではライトはオフです。

ライトオフ

Exメニューの「ライトオンオフ」を押すと、電球マークが表示されます=ライトオン。

ライトオン

ライトオン状態でExメニューの「明るさ調整」を変化させると、ライトの強度が変化します。

明るさ調整(ライト強度が強い状態)

Exメニューの「色相調整」を変化させるとライトの色が変わります。(電球マークの色で表される。)

色相調整

すべてが想定通り動けば動作確認は完了です。
アバターアップロードしてvrchat内で確認してみてください。(ローカル化の確認は自分だけではできないので、フレンドと会ったときに試してみてください。)

お疲れさまでした。以上で光源ライトギミックの実装の解説は終了となります。

おわりに

ここまで読んでくださりありがとうございました。
今回はboothでの初出品に伴って、ギミックの実装内容について解説しました。こういう知見は広めると商品価値が下がるように思えますが、界隈が発展すれば巡り巡って全体の利益になると思っています。

それでもモチベーションにつながるのでリンクから光源ライトギミックの購入もよろしくお願いいたします。ここまで読んだ人は自分で実装できますので、自信を持って自作に取り組むのもまた良しです。皆さんも改変、しよう!ということで。

今回の知見が誰かの役に立てば幸いです。

(有料部分にはコンテンツはありません。この記事を気に入っていただけたなら、ご支援いただければ幸いです。)


2024/09/26
written by shift

ここから先は

14字

¥ 100

この記事が気に入ったらチップで応援してみませんか?