なつねこメモ

主にプログラミング関連のメモ帳 ♪(✿╹ヮ╹)ノ 書いてあるコードは自己責任でご自由にどうぞ。記事本文の無断転載は禁止です。

VRChat で使えるタッチで取り出し・収納可能なギミックを作りたい

朝のラジオ体操に出かけてから毎日が楽しい私、みかです (VRChat の話です)。
VRChat でも使えるちょっとしたギミックを作ったので、
忘れないうちに仕組みを書いておきます。

なお、このギミック自体は Animation Override を使用していません。
(Particle System と Animation はそこそこ大量に使用します。)


前書き:

  • Animation も Particle も初めて触ったから変なところあっても許してね

作ろうとした動機:

前提環境:

  • Unity 2018.4.20f1 Personal
  • VRChat 2020.1.1p4

リポジトリはこちらです:

GitHub - mika-archived/VRChat-InventorySystem

どんな仕組み?というと、意外と単純で、以下の動作を組み合わせたものになります。

  • Particle System の Triggers と SubEmitters
  • Unity の Animation Controller の State の仕組み
    • Object を Activate/Deactivate で Entry に戻る
    • Animator を Activate/Deactivate で状態を保存
    • keepAnimatorControllerStateOnDisable で Disable でも状態を保存

各 GameObject の構造は下のような感じで、

f:id:MikazukiFuyuno:20200426221634p:plain

Inventory(XXX)Slot[X]_Object(XXX) の 2 つ GameObject ツリーからなります。

Inventory(XXX) は、当たり判定を行っています。
こちらの仕組みは単純で、最低限以下の 2 つの GameObject さえあれば良いです。

  • Inventory(XXX)
  • Collider

(中間の Slot[X]_Inventory は適当な当たり判定可視化用 3D Object です。)

Inventory は以下の Animation Controller が設定された
Animator Component のみがアタッチされています。

f:id:MikazukiFuyuno:20200426221815p:plain

Animation Controller

中身は 1 サイクルで孫の Collider を Activate/Deactivate しているだけです。
これは、孫の Collider が死んでもまた復活して、再度当たり判定が
有効になるようにしています。

次は Collider GameObject です。
こちらには Particle System がくっついていて、以下のような設定です。

f:id:MikazukiFuyuno:20200426221935p:plain

Particle System の設定

重要なのが Triggers の項目で、ここである Object が Particle 内部に入ったら、
自身を殺して、 Sub Emitters で Slot[X]_Object(X) の子にいる Trigger を呼び出します。

次は Slot[X]_Object(X) の方にはいります。
こちらは少し複雑で、一番下の Object とその子以外は全て Animator がくっついています。 まずは先ほど親から飛ばされてきた Trigger から見ていきます。
Triggers は下のような Particle System がついています。

f:id:MikazukiFuyuno:20200426222019p:plain

Triggers の設定

Play On Awake を外すことと、 Stop ActionDisable にするのが重要です。
Stop ActionDisable に設定することで、生存期間が終了すると、
このパーティクルは自動的に Deactivate されます。
Deactivate されると、親にいる Enabler が再度この GameObject を Activate し、
結果的には死んだタイミングで Entry に設定された Animation が再生されるようになります。

次は Trigger の孫にいる ObjectProxy です。
これは、keepAnimatorControllerStateOnDisable = true が設定されています。
この GameObject に設定された Animator は以下のようになります。

f:id:MikazukiFuyuno:20200426222057p:plain

Animation Controller

ObjectProxy の子の状態にも寄りますが、初め Disabled の場合は、
上記のような Animation State を持っています。
Activate/DeactivateObject は名前のままの処理を、
SuspendAsActivated/Deactivated は自身の Animator を無効にしています。
Animator を Disabled にすることで、現在の状態を維持しているわけです。
ただし、そのままだと親の Particle が死んだ段階で状態が失われるので、
keepAnimatorControllerStateOnDisable も有効にしているのです。

ということで、コアな部分の解説はこんな感じでした。
残りの部分は、実際の Prefab を見てもらえれば理解できると思います。

ではでは~ヾ(๑╹◡╹)ノ"