VRChatのアバターに連打で何度も音が鳴るギミックを入れたい!

VRChatのアバターに連打しても音を鳴らせるギミックを入れたくて、アニメーションをいい感じに組んだよという話です。

色々な人に教えてもらってうまくいったので、その知見を共有します。

どんなギミック?

アクセサリーに触ると音が出るギミックで、触るたびに音を鳴らすことが出来ます

…と説明するよりも見てもらったほうが早いかもですね、動画を貼りました。

youtu.be

作り方

流れとしてはこんな感じです。そんなにやることは多くないですね。

  1. アクセサリーに VRCContactSender を入れる
  2. AudioSource を追加する
  3. AudioSource のアクティブ状態を切り替えるアニメーションを用意する
  4. Animator を組む

ここではContactsやアニメーションについては詳しく書かないので、他のドキュメントを読んでみてください。

1. アクセサリーに VRCContactSender を入れる

触ったときにパラメータを変更したいのでVRCContactSenderを入れます。

詳しい説明は割愛しますが、当たり判定の範囲調整と、手もしくは指が触れたときに GBC Contact というパラメータが変化するようにしています。

Receiver Type は On Enter にしておくことで、触られたときに1フレームだけパラメータが変化するようにします。

VRCContactReceiverの設定

2. AudioSourceを追加する

VRChatのアバターではスクリプトを使えないので、AudioSourceの「Play On Awake」をオンにしておきましょう。

これで、AudioSourceがActiveになったときに音が鳴るようになります。

Audio Souceの設定

3. AudioSource のアクティブ状態を切り替えるアニメーションを用意する

タイトルのとおりですが、Activeを切り替える対象はAudioSourceコンポーネントでもAudioSourceがついているGameObjectでもどちらでも問題ないです。

ここでのポイントですが、

  • 0フレーム目に AudioSource の Is Active をオフにする
  • 1フレーム目に AudioSource の Is Active をオンにする

というふうにすることで、アニメーションの再生開始時に必ず音が鳴るようになります。

アニメーションの0フレーム目

アニメーションの1フレーム目

ただ、これだけだとAudioSourceがオンのままになるので、あとからワールドにJoinするなどしてアバターが読み込まれたタイミングで音が流れてしまいます。

なので、音を鳴らし終わる秒数あたりでオフにしておきます。

今回は鳴らす音の長さが 0.824秒だったので、余裕を取って1秒でオフにするようにしました。

最終的にこのようになりました。

音を鳴らす用のアニメーション

4. Animatorを組む

Animatorを組む際に最低限必要なのは、次の3つです。

  • Sound On に先ほどつくったアニメーションを指定、Idle には何もアニメーションを指定しない
  • Any State から Sound On に遷移させる
  • Any State -> Sound On の Can Transition To Self をオンにする

Animatorの設定

AnyState -> Sound On の設定

おわり

GestureManager などで動作確認してみて問題なければアップロードして完成です!

Animator はやり方がたくさんあってなかなか難しいですね…

このやり方は、おそらくパフォーマンス的にも問題がないと思いますが、他にいい方法があるよという人はぜひ教えてください。