こかげむら

ゲーム好きな理系大学生のお話

webカメラで撮った自分の顔の動画から心拍測ってみた

顔の動画から心拍が測れるらしい

前にちらっと,顔の動画から心拍を図ることができると聞いたことがあったが,にわかには信じられない.ネットで検索していると実際にやってる方がいたのでその記事を参考にさせてもらいながら,自分でもやってみた.

qiita.com

顔の動画から心拍が測れる原理

  • 心拍によってヘモグロビンの量が変化
  • ヘモグロビンは緑の光を吸収する特性がある
  • 顔とカメラを動かさないように固定し,動画を撮って顔の一部のRGB値のGを時系列でプロットすると,心拍が出てくる

つまり,人間の顔色は緑色っぽくなったり,ならなかったりを繰り返しているってことらしい.目で見ても全然わからないから早速やってみる.

実際にやってみた

  1. 自分の顔をできるだけ動かさないようにしてPCのwebカメラで撮影する
  2. 顔の頬の部分のピクセル位置を探す(手作業)
  3. 上の記事のプログラムをコピペして顔の部分のピクセル位置だけ変えて実行
  4. 画像のG値(緑)をプロットすると以下のようになった

f:id:agry:20191004071721p:plain

 確かに緑色の値が大きくなったり小さくなったりを周期的に繰り返している.顔の固定も甘かったし,蛍光灯の光しか当ててないから参考にさせてもらった記事ほどきれいに出なかったけど.

信じられなかったけど,顔は緑色になったりならなかったりしているらしい.

思ったこと

力を入れている部位にはほかの部位に比べて血が多く流れて,ヘモグロビンの量が多くなっていると仮定する.(ソースはない,思いつき)

上の仮定が正しければ画像から力を入れている部位を検出できるんじゃないか?と思って,自分の腕の動画を撮影し,力を入れていない時と入れているときを比較してみた.

解析する腕の位置が若干ずれていたり,撮影してるとき腕が振るえてしまったりと,結構適当に実験したから,正確な値ではないと思うけど一応結果を載せる.

力を入れてない時(左),力を入れてる時(右)

f:id:agry:20191004071818p:plainf:id:agry:20191004071931p:plain

もしかすると力を入れているときはヘモグロビンの量が多くなってG値が低くなってる?

上手く撮れてないだけかも.また追実験してみて結果を書こうと思う.

 

【備忘録】ロジスティック回帰のアルゴリズム

はじめに

ロジスティック回帰の処理の流れ,学習アルゴリズムについて勉強したので忘れないうちに書いておく

処理の流れ

処理の流れはADALINEやパーセプトロンと同じ
初めに総入力関数z

z = \sum w^Tx

総入力関数の計算結果をアクティベーション関数\phi(z)に入れる

\phi(z) = \frac{1}{1 + e^{-z}}

最後にアクティベーション関数の計算結果をもとにアウトプットyを計算する

\dot{y} = \left \{ \begin{array}{l} 1 (\phi(z)>0.5のとき) \\ 0 (\phi(z) < 0.5のとき) \end{array} \right.

アクティベーション関数\phi(x)について

ロジスティック回帰のアクティベーション関数\phi(z)シグモイド関数と呼ばれており,このシグモイド関数の出力はサンプルがクラス1に属している確率であると解釈される.なのでアウトプットyを計算する時,0.5が閾値になっていて,xがクラス1に属する確率が50%以上ならy=1,50%未満ならy=0となっている.実際のところ,多くのアプリケーションでは,予測されるクラスラベルに関心があるだけでなく,クラスの所属関係の確率(アウトプットにする前のシグモイド関数の出力)を見積もることが特に有益になる.

モデルの学習

ロジスティック回帰では,モデルの学習時に尤度L(w)を最大化したいと考える

L(w)=P(y|x:w)=\prod_{i=1}^n P(y^{(i)}|x^{(i)};w)=\prod_{i=1}^n(\phi(z^{(i)})^{(i)}(1-\phi(z^{(i)}))^{1-y^{(i)}}

計算のしやすさから尤度Lの対数をとった対数尤度l(w)を定義し,これを最大化することを考える

l(w) = logL(w)=\sum_{i=1}^n (y^{(i)}log(\phi(z^{(i)}))+(1-y^{(i)})log(1-\phi(z^{(i)})))

勾配降下法を使ってwを更新したいので,l(w)の正負を反転させ,最大化問題を最小化問題に置き換える

max(l(w)) = min(-l(w))

↑がコスト関数J(w)となる

J(w)= \sum_{i=1}^n (-y^{(i)}log(\phi(z^{(i)}))-(1-y^{(i)})log(1-\phi(z^{(i)})))

重みwの更新式はADALINEと同じように勾配降下法を使って更新していく

w := w+\Delta w
\Delta w=-\eta\nabla J(w)=\eta\sum_{i=1}^n (y^{(i)} - \phi(z^{(i)}))x_j^{(i)}

この重みの更新式はADALINEと全く同じになっており,ADALINEとロジスティック回帰で異なる点はアクティベーション関数\phi(z)\phi(z)=zを使うか,\phi(z) = \frac{1}{1 + e^{-z}}を使うかの違いだけ.

【前処理大全】サンプリングをする時は単位を揃えよう

はじめに

データの前処理,サンプリングの時の注意点の話

機械学習について勉強していて,そこでは前処理が大切になってくる

最近『前処理大全』という本を読んでいて,サンプリング時に大切だと思った点,注意しなければならないと思ったことについて書く

コードはPythonです.

前処理大全[データ分析のためのSQL/R/Python実践テクニック]

前処理大全[データ分析のためのSQL/R/Python実践テクニック]

 

 サンプリング

業務でデータを扱って分析などを行う際,データサイズが膨大でそのままではメモリに乗らないということがある.

そんな際に膨大なデータの一部分だけを抽出することをサンプリングという.

結論:分析対象データの単位とサンプリング単位は揃えよう

そうしないと,サンプリングによってデータを破壊してしまう

実際に検証してみる

検証に使うデータ reserve_tb

f:id:agry:20190907131713p:plain

データについて

ホテルの予約レコード.1行に1つの予約が格納されてる.

列(カラム)は予約id,ホテルid,顧客id,日時,予約人数などの予約に関する情報

比較する分析対象について

 分析対象1:予約人数別の予約数について調べる

     例)予約全体のうち,4人で泊まる予約がされたのは何件あるのだろう?

 

分析対象2:年間の予約回数別の顧客数について調べる

     例)年間で5回予約してくれた顧客idは何種類あるのだろう?年間で1回しか予約しない顧客idは何種類あるのだろう?

サンプリング手法

#検証に使うデータreserve_tb
half_reserve_tb = reserve_tb.sample(frac=0.5)

分析対象1,2どちらについても,予約の50%を抽出するようにサンプリングする.

予約数が50%になるようにサンプリングするので,この場合サンプリングの単位は「予約数」

つまり分析対象1は分析対象とサンプリング手法の単位が揃っているが,分析対象2は単位が異なっている

分析対象1,2のサンプリング前後を比較してみた

 分析対象1(単位が揃ってる良い例)

サンプリング前(左),サンプリング後(右)

サンプリングの前後でデータの分布はほとんど同じ

f:id:agry:20190907140454p:plainf:id:agry:20190907140714p:plain

分析対象2(単位が異なっている悪い例)

サンプリング前(左),サンプリング後(右)

サンプリングの前後でデータの分布が異なる

f:id:agry:20190907141221p:plainf:id:agry:20190907141238p:plain

分析対象2の時の適切なサンプリング手法

以下の手順でサンプリングする必要がある

  1. 予約レコードの顧客IDに対してサンプリング
  2. サンプリングした顧客IDの予約レコードのみを抽出する
#予約レコードの顧客ID(ユニークなもの)に対してランダムサンプリング
#targetにサンプリングした顧客IDを格納
target = pd.Series(reserve_tb['customer_id'].unique()).sample(frac=0.5)
#targetに含まれる顧客IDのみ抽出
reserve_tb[reserve_tb['customer_id'].isin(target)]

分析対象2で単位を揃えたサンプリングを行った時の結果

サンプリング前(左),サンプリング後(右)

サンプリングの前後でデータの分布がほとんど同じ

f:id:agry:20190907142114p:plainf:id:agry:20190907142130p:plain

思ったこと

確かに分析対象とサンプリング単位が異なればサンプリングの前後でデータの割合が異なってしまう.

例えばこの場合だと,サンプリング前のデータでは,年間7回予約していた顧客が,50%サンプリングによって7回全ての予約データが取ってこられるとは限らない(期待値的に7回のうち3,4回しか取ってこられないだろう).したがって,予約回数が少ない顧客の割合が増加してしまい,サンプリングによってデータを破壊してしまっている.

サンプリングは分析対象のデータとサンプリング単位を揃えることが重要.

【備忘録】パーセプトロンの学習規則

脳内のニューロンの働きを模倣した要素還元主義的なアプローチ,パーセプトロンモデルの学習規則について今日勉強したことを書いていく.

 

パーセプトロンアルゴリズム

入力xと重みベクトルwを以下のように置くと

w = \left(\begin{array}{rrr}w_1\\ w_2\\ \vdots\\ w_m \end{array}\right)   x = \left(\begin{array}{rrr}x_1\\ x_2\\ \vdots\\ x_m \end{array}\right)

 

総入力z = w_1 + w_2 + ... + w_m = w^T xと表される.

 

パーセプトロンアルゴリズムでは決定関数\phiは単位ステップ関数になっていて次の式で表される.

\begin{eqnarray}\phi (z) = \left\{ \begin{array}{ll}
1 & (z\geqq\theta) \\
-1 & (z<\theta) \end{array} \right.\\\end{eqnarray}

総入力zが変数となって出力outputが決定されていき,そのoutputをもとに重みが更新されていく.

重み更新の手順

1.重みw0または値の小さな乱数で初期化(適当に値を決める)

2.トレーニングサンプルx_iに対するラベルy_iを用意する(教師データ)

3.出力値outputを計算

4.重みを更新(間違えたら更新)

これらをひたすら繰り返して最適な重みを見つける

重みの更新式

w_i := w_i + \Delta w

\Delta w = \eta (y_i - output)x_i 

\etaは学習率で0以上1未満

例えばここで,出力値1でラベルも1で,出力値とラベルが合致しているときは

\Delta w = \eta (y_i - output)x_i = \eta (1 - 1)x_i = 0

となり

w_i := w_i + \Delta w = w_i + 0 = w_i

なので,更新されない.

合致していない時は,\Delta w_iが0にはならないので重みが更新される.

Unity上のHumanoidアバターで姿勢を判定(採点)しようとして苦労した話

まえがき

大学の研究でPerceptionNeuron2.0とUnityを使用して、とあるアプリケーションを開発しているのですが、開発していて苦労した(している)、Unity上のHumanoidアバターで姿勢の判定を行う手法の話をしたいと思います。

f:id:agry:20181117191157p:plain

それとはあまり関係ありませんが最近Viveとトラッカーを購入し、フルトラVRChatにドハマりしていて、VR世界に自分の体を入れられる!!モーキャプってすげー!!ってなっています。

やろうとしたこと

PerceptionNeuronでUnity上のHumanoidアバターを動かし、姿勢を判定(採点)しようとした。

例えば、下の図のような女の子座りをお手本の姿勢とします。PerceptionNeuronを使って自分の体でHumanoidアバターを操作して、下の図と同じ女の子座りの姿勢をとることができているか、アバウトに判定(関節の曲がり具合などが同程度か判定)がしたいという感じです。

f:id:agry:20181117173508p:plain

試してみて上手くできなかった手法

いくつかの手法を試しました。

3DCGの世界では姿勢の計算などにクオータニオンという四元数が良く使われるらしいので、模範姿勢の各関節のクオータニオンを計算してそれに近い値を取れていたらOKとしてみたり。UnityのInspectorから弄れる値localEulerAngleなどのオイラー角を使ってみたり(ジンバルロックさん...!?)。

とにかく閾値の設定が面倒だし、プログラムは汚く複雑になるし、デバッグとか細かい調整とか絶対やりたくない。

(ここに書かれているのは僕が技量不足のために実現できていないだけかもしれません。)

Unity初心者の独断と偏見での結論

ここに書く結論はUnity初心者の考えであり、もっと良い方法があるかもしれませんし、もしあるのであれば教えてほしいです。切実に。

アバウトに姿勢を判定したいのであれば、アバターのHipなどの子オブジェクトとして、Colliderを設置してあげて、そのColliderに指定した関節が入っているか(下の図のような感じ)で判定するのが良いのではないかという結論に至りました。

f:id:agry:20181117180233p:plain

例えば、HeadCheckというオブジェクトは模範姿勢を真似する上で、アバターのHeadがあるべき位置に設置されています。ほかのColliderObjectも同様に設置されています。

f:id:agry:20181117181548p:plain

従って、上の図のようにColliderObjectの位置に指定された関節部位を入れることで、模範姿勢と同じ姿勢をとることができます。

末端の関節(手先や足先、頭など)まで完璧に同じ姿勢が取れているか判定することはできないかもしれませんが、アバウトに判定したいのであればこの方法が使えるかと思います。

もし判定を厳しくしたり、末端の関節の判定まで完璧に行いたいのであれば、ColliderObjectをさらに小分けにして、細かく判定してあげれば良いのではないかと思います。逆にColliderを大きくすれば判定を甘くすることもできますね。

ちなみにColliderに指定された部位が入っているかどうかの判定を行うのはC#であればOnCollisionStay()を使えばできます。(RigitBodyとIsTrrigerを忘れずに)

marunouchi-tech.i-studio.co.jp

まとめ

姿勢判定を行うことができれば、「あるポーズをとったら変身!」とか、「両手を腰の右隣に持ってきたらかめ◯め波をチャージ!」とか、色々なことができます。

今回はColliderはHumanoidアバターの姿勢を判定するのにも使うことができるという話でした。時間があれば何か面白いゲームでも作ってみたいです。

f:id:agry:20181117185447p:plain

あとがき

今回いろいろやってみて分かったことはこれです。

スクリプトで姿勢を判定するよりも、当たり判定を使って実現した方が目で見てわかりやすいですし、細かい調整もかなり楽です。

なかなかいい方法が思いつかなくて苦労しましたが、その過程でクオータニオンのことや、Unityの細かい機能のことなど、様々なことを勉強できたので良しとします。

www.f-sp.com

© Unity Technologies Japan/UCL

VRChatで長いアニメーションを実装する方法【VRChat】

VRChatのアップデートでLegacyAnimationが使用できなくなったため、この手法は使用できなくなりました

f:id:agry:20180901224731p:plain

今回はVRChatでオブジェクトに長いアニメーションを持たせる方法を紹介したいと思います。

通常、VRChatでアニメーションオーバーライドに2フレーム以上のアニメーションを割り当てるとおかしな挙動になってしまいます。 

ですがこの方法を使えば、おかしな挙動になってしまうのを回避することができます。

 

以下VRCSDKなどが導入済みであることを前提に話を進めていきます。

VRChatにアバターを一度もアップロードしたことがない人は下の記事を参考にしてください

前提知識

 

f:id:agry:20180901215647p:plain

www.moguravr.com

shiasakura.hatenablog.com

 

 

1.アニメーションを導入したいオブジェクトを用意する

今回はこのゴスロリ風洋傘を使用し、この傘に対してアニメーションを割り当てていきます。

a-lapin.booth.pm

 

ダウンロードした洋傘モデルをUnityに入れ、Hierarchyに持ってくる。

f:id:agry:20180901211422p:plain

2.傘を開く、閉じるアニメーションを作成する

導入が終わりましたら、ここから長いアニメーションを作成していきます。

長いアニメーションは、アニメーションオーバーライドで再生するのではなく、オブジェクトがIs activeになった時に自動的に再生させる方法で再生させます。

実際に作っていきましょう。

1 洋傘を選択

2 animationウィンドウで新たに「傘開く」「傘閉じる」という名前のアニメーションクリップをcreateします。

f:id:agry:20180901212152j:plain

 

2-1.「傘開く」アニメーションの作成

傘が閉じた状態から、開いた状態にするアニメーション「傘開く」を作成していきます。

洋傘をctl+Dで複製し、「洋傘閉じてる」という名前に変更します。

f:id:agry:20180901213214p:plain

次に、「洋傘閉じてる」を選択し、InspectorでSkinned Mesh RendererのBlendShapesを開き、"開閉"の値を100にします。

f:id:agry:20180901213452p:plain

これで閉じた状態の傘が完成しました。

そうしたら傘が開くアニメーションを作成します。

1 animationウィンドウで録画ボタンを押す。

2 0秒のところでSkinned Mesh RendererのBlendShapes開閉の値に100を入力。

3 3秒のところで開閉の値に0を入力。

f:id:agry:20180901213916p:plain

これで3秒かけて傘が開いた状態になるアニメーションクリップを作成することができました。

次に「傘開く」アニメーションクリップを選択し、Inspectorの右上(鍵マークの右隣)のアイコンをクリックし、Debugモードを選択します。

f:id:agry:20180901214612j:plain

Debugモードに入ったら、Legacyにチェックを入れます

f:id:agry:20180901214840p:plain

下の図のように「傘開く」アニメーションクリップのInspectorがWrap Modeと表示されていたら。「傘開く」が完成です。

完成したら、DebugモードからNormalモードに戻しておきましょう。

f:id:agry:20180901215508j:plain

2-2.「傘閉じる」アニメーションの作成

「傘閉じる」は傘が開いた状態から閉じた状態にするアニメーションです。作り方は「傘開く」とほとんど同じです。

区別のために「洋傘開いてる」オブジェクトを作成します。

f:id:agry:20180901215618p:plain

「傘開く」と同じように

1 「傘閉じる」に対して、animationウィンドウで録画ボタンを押す。

2 0秒のところでSkinned Mesh RendererのBlendShapes開閉の値に0を入力。

3 3秒のところで開閉の値に100を入力。

f:id:agry:20180901220221j:plain

これができたら、「傘閉じる」のアニメーションクリップを選択し、DebugモードでLegacyにチェック。

f:id:agry:20180901220345p:plain

Legacyにチェックしたら、Normalモードに戻しておきましょう

これで「傘開く」「傘閉じる」の2つのアニメーションクリップが完成しました。

3.Animationコンポーネントをセットする

Hierarchyから「洋傘閉じてる」オブジェクトを選択し、InspectorでAdd ComponentからAnimationコンポーネントを入れます。

f:id:agry:20180901220950j:plain

AnimationコンポーネントのAnimationの欄に、先ほど作成した「傘開く」アニメーションクリップをドラッグ&ドロップします。

f:id:agry:20180901221233j:plain

これを「洋傘開いてる」オブジェクトに対しても、同じようにして「傘閉じる」アニメーションクリップを入れてあげます。

f:id:agry:20180901221812j:plain

これでセット完了です。

4.アニメーションオーバーライドでオブジェクトを取り出す

ここまでくれば後は簡単です。

「洋傘開いてる」「洋傘閉じてる」を持たせたい部位に入れて、2つとも同じ位置になるよう調整します。今回は右手に入れたいと思います。

f:id:agry:20180901222417j:plain

f:id:agry:20180901222530j:plain

そうしたら「洋傘開いてる」「洋傘閉じている」の表示を消して

f:id:agry:20180901222747p:plain

使用したいアバターを選択して、animationウィンドウで「傘閉じてる発生」「傘開いてる発生」の2つのアニメーションクリップを作成。

f:id:agry:20180901223036p:plain

「傘閉じている発生」では「傘閉じてる」をIs activeにするアニメーションを0フレーム目と1フレーム目に設定

f:id:agry:20180901223330p:plain

「傘開いてる発生」では「傘開いてる」をIs activeに

f:id:agry:20180901223407p:plain

これで完成です。

5.アニメーションオーバーライドの設定

4で作成した「傘開いてる発生」「傘閉じてる発生」をアニメーションオーバーライドに割り当てます。

f:id:agry:20180901223619p:plain

これでアバターをアップロードすれば、傘を召喚したときに、開く閉じるの動作が勝手に再生され、長いアニメーションをアニメーションオーバーライドで呼び出せた(?)ことになりました。

6.まとめ

今回はVRChatで2フレーム以上の長いアニメーションを実装する方法を紹介しました。

このブログで使用している、ポンデロニウム研究所のフェンサーちゃんや、クレリックちゃんのアバターには、最初からクオリティの高いアニメーションが付属されてくるのですが、それに感動して、自分でも作ってみたくなり、情報を集めて実装してみました。

説明が長くなってしまいましたが、実装できましたでしょうか。この方法を使えば、傘の開閉以外にも様々なオブジェクトに対して長いアニメーションを持たせることができると思います。

皆様もよきVRChat生活を!

GPUパーティクルの導入方法【VRChat】

今回はVRChatで最近流行っている(?)GPUパーティクルの導入方法を紹介します。

GPUパーティクルを導入すると下のような魔法のようなものをVRChatに召喚することができます。

以下VRCSDKなどが導入済みであることを前提に話を進めていきます。

VRChatにアバターを一度もアップロードしたことがない人は下の記事を参考にしてください

www.moguravr.com

 

1.GPUパーティクルのダウンロード

GPUパーティクルはQuantum氏が制作したものが配布されているのでそちらを使わせていただきます。こちらのDiscordサーバの#downloadsチャンネルからGPU_Particles_v2.unitypackageをダウンロードします。

discord.gg

 

 2.Unityにパッケージをインポート

Unityを開きAssets->Import Package->Custom Packageから先ほどダウンロードしてきたGPU_Particles_v2.unitypackageをインポート

f:id:agry:20180809125137p:plain

f:id:agry:20180809125437p:plain

下のようにGPU Particlesが導入されていればOKです。

f:id:agry:20180809130040p:plain

 

3.アバターGPUパーティクルを入れる(VRモード)

 VR機器を使用してVRChatを遊ぶ人向けです。 

1.GPU Particlesの中にあるVR 2-HandedをHierarchyに入れてください

f:id:agry:20180809130711p:plain

 

2.VR 2-Handedの中にあるParticlesを、導入したいアバターのArmatureと同じ階層に入れます

f:id:agry:20180809131306p:plain

このとき、このような表示がでると思いますが、Continueを押してください。

f:id:agry:20180809131516p:plain

 

3.VR 2-Handedの中にあるCamera1を左手首へ、Camera2を右手首へ

f:id:agry:20180809131907p:plain

f:id:agry:20180809132005p:plain

下のようにCamera1,Camera2を入れることができていればOKです。

f:id:agry:20180809132342p:plain

 

 4.Camera1,Camera2のポジションをそれぞれ左手、右手の位置に合わせます。(Camera2も同じようにやってください)

f:id:agry:20180809132728p:plain

 

3.アニメーションを作成する

 GPUパーティクルをアバターに入れることができたので、それを表示するアニメーションを作成していきます。

まずAnimationウィンドウで、activate、push、pause、resetの4つのアニメーションクリップ(名前はなんでもいいです)を作成します。

f:id:agry:20180809210854p:plain

 

activate 

acitivateから弄っていきます。Animationウィンドウの赤い丸(録画ボタン)を押してアニメーションを録画します。そうしたら、下の画像のようにParticle、Camera1、Camera2の赤丸で囲まれた部分をクリックしてアニメーションを作成します。

f:id:agry:20180809211653p:plain

f:id:agry:20180809212208j:plain

f:id:agry:20180809212220j:plain

 

合計5つのアニメーションが出来たと思うので、それらすべてを2フレーム目にコピーします。これでactivateクリップは完成です。

f:id:agry:20180809212608p:plain

 

push 

次にpushです。activateと同じように録画ボタンを押して、Camera1の子のSimulator1を選択、InspectorのSimulator1 vrシェーダーを▷を押して開きます。

f:id:agry:20180809213133p:plain

 

Simulator1 vrのAttractionの値を-0.01に変更します。これと同じ操作をCamera2のSimulator2に対しても行ってください。

f:id:agry:20180809213351p:plain

 

作成した2つのアニメーションを2フレーム目にもコピーしてあげて、pushも完成です。

f:id:agry:20180809213649p:plain

 

pause

pauseです。録画ボタンを押してから、下の画像の赤丸部分を押して、Camera1の子のSimulator1とCamera2の子のSimulator2を非表示にするアニメーションを作成します。

f:id:agry:20180809214450p:plain

 

作成した2つのアニメーションを2フレーム目にもコピーして完成です。

f:id:agry:20180809214540p:plain

 

reset

最後にresetです。録画ボタンを押してから、Simulator1の、下の画像の赤丸部分(Element0)にGPU Particles/ResourcesのResetマテリアルをドラッグアンドドロップします。

f:id:agry:20180809215326p:plain

これをSimulator2に対しても行ってください。

 

作成した2つのアニメーションを2フレーム目にもコピーしてresetも完成です。

f:id:agry:20180809215615p:plain

 

4.アニメーションオーバーライドの設定

アニメーションオーバーライドの設定は下の記事も参考になると思います。

shiasakura.hatenablog.com

作成したアニメーションをアニメーションオーバーライドの任意の場所に入れます。

f:id:agry:20180809220052p:plain

 

これでアバターをアップロードすればGPUパーティクルが使えるようになっているはずです。

GPUパーティクルはCameraを使用しているため、フレンドにしか見せることができません。これを口実にフレンドを増やしましょう(笑)

 

5.GPUパーティクルの使い方

reset->activateの順にアニメーションを再生してください。すると手の位置(Camera1、Camera2の位置)に粒子が集まってくるはずです。花火のように粒子を広げたいときはpushアニメーションを再生してください。

 

6.まとめ

GPUパーティクルの導入方法を紹介しました。なかなか複雑な手順でしたが、一度導入してしまえばGPUパーティクルで無限に遊んでられるので、頑張ってください。みなさんもよきVRChatライフを!