MEBIUSTOSのブログ

主にUnityに関する技術的な事を書いていきます。 Twitter @xflutexx

スクリプトで呼吸させる - 第2回 | Unity3D

f:id:mebius-tos:20150830203119j:plain

そもそも

リアルな人間が呼吸をする場合、息を吸えば胸が膨らむし、横隔膜だって動くからお腹も動く。でも、Unityのヒューマンモデルで呼吸を実現するとなるとそうはいかない。骨の動きだけでそれっぽく見えるようにしないといけない。そんな制限条件付きの、実に日本人向けなプロジェクトとなっております。
(2015/9/5 追記:プログラミング生放送さんにて紹介記事を書いて頂きました。感謝!)

実際に動かした骨

実際にスクリプトで動かした骨は、Spine,Chest,Neck,Head,Shoulder(or UpperArm)の5つ。Shoulderは呼吸した際に腕が不自然に揺れるのを防いでいるだけです。なので実際は4本の骨の傾きのみで実現しています。できればSpineよりも下の骨も動かしたかったんですが、それを実現しようとすると途端に色々と問題が浮上してきたのでやめました。

骨のローカル座標系の向き

モデル毎に骨のローカル座標系の向きってバラバラなんですね。初めて知りました。。。X軸が体の前方むいてたり、Z軸が体の前方むいてたり。しかもその骨のローカル座標系から見て、どの方向が体の前方なのか後方なのかを正しく調べる方法が分かりませんでした。しかたないので、骨のローカル座標系X軸、Y軸、Z軸とワールド座標系との内積から、どの軸が一番それっぽいかをファジーに判定しています。なので、シーン開始時などにおいて極端に体をひねったポーズを取っていると軸判定に誤りが生じるかもしれません。

人間工学に基づくアプローチ

  • 人間の吸気時の吸気量曲線はsinカーブに似ているらしいので、吸う時のイージングはEaseOutSine曲線を、吐く時はEaseInOutQuad曲線を採用。
  • 「息を吸う」、「息を吐く」だけではなく、「息の休止期」も考慮。
  • 上記を踏まえた上で、Unity上で不自然にならないよう調整。

そして出来たものがこちら

注意: 小さい画面だと分からないかもしれません

ダウンロード(beta版)

BreathController
(2019/06/23 ソースコードにMITライセンスについての記載を追加。)

使い方

Humanモデルにアタッチして使用してください。(HumanモデルにはAnimatorControllerがアタッチされている必要があります)

DurationRate
呼吸1サイクルに要する時間を調整します。大きくすると遅くなります。小さくすると早くなります。初期値は1で、2にすると1回の呼吸に倍の時間がかかります。最小値は0です。

EffectRate
呼吸の深さを調整します。大きくすると深くなります。小さくすると浅くなります。初期値は1で、2にすると各骨が倍の角度で回転します。最小値は0で、呼吸しなくります。

ケーススタディ

参考程度にケーススタディを記載します。個人的な好みで控えめな設定値になっています。もう少し派手に動いて欲しい場合は、DurationRateを上げて調整してください。また、モデルによっても見え方が変わってきます。Tda式AppendミクさんはEffecRate1.2~1.3くらいがちょうど良かったです。まぁ、どんな感じで調節すればよいかの指標になれば幸いです。

通常時

DurationRate: 1 / EffectRate: 1
通常時の落ち着いた呼吸。

睡眠時、モルヒネ中毒時、呼吸筋の麻痺時

DurationRate: 1 / EffectRate: 0.7
速度は変わらず、浅くなる。

発熱時、興奮時

DurationRate: 0.5 / EffectRate: 1
速度が早くなる。深さは変わらず。

運動時、高熱時、神経症

DurationRate: 0.3 / EffectRate: 2
速度が早くなり、深くなる。

貧血時(過呼吸

DurationRate: 1 / EffectRate: 2
速度は変わらず、深くなる。

末期患者

DurationRate: 1.6 / EffectRate: 0.7
速度が遅くなり、浅くなる。

HeadLookControllerとの併用

HeadLookControllerはLateUpdate内でLookAt処理を行っており、本BreathControllerも呼吸処理をLateUpdate内で行っています。その関係上、HeadLookControllerがBreathControllerの後に実行されると、呼吸処理による骨の回転がHeadLookControllerにて上書きされ無効化されます。
そこで、下記の手順にてスクリプトの実行順を明示的に指定してやる必要があります。

  1. メニュー: Edit > Project Settings > Script Execution Order で Script Execution Order 設定を開く。
  2. Default Timeの部分にHeadLookController.csとBreathController.csをそれぞれドラッグし、BreathController.csがHeadLookController.csの下になるよう設定します。
    f:id:mebius-tos:20150830162336j:plain

HeadLookController以外にもLateUpdate内で骨の回転を制御するようなスクリプトが存在する場合は、そのスクリプトも追加する必要があるかもしれません。

スクリプト実行順の詳しい説明は下記の公式リファレンスを参照してください。
http://docs.unity3d.com/ja/current/Manual/class-ScriptExecution.html

詳細設定 (Advanced Config)

呼吸時間(吸う、吐く、停止)や、各骨の回転量を詳細に設定できます。

Duration

呼吸時間の詳細設定です。実行時にはDurationRateが乗算されて最終的な秒数が算出されます。

Inhale
息を吸うのに要する秒数です。
Exhale
息を吐くのに要する秒数です。
Rest
息を吐いた後の停止秒数です。

Angle

各骨がオリジナルの角度から最大何度回転するかを設定します。実行時にはEffectRateが乗算されて最終的な回転角度が算出されます。

[BoneName]Inhale
息を吸った時の骨の回転量です。+で胸側へ、-で背側へ回転します。
[BoneName]Exhale
息を吐いた時の骨の回転量です。+で胸側へ、-で背側へ回転します。

調整のポイントは、吸った時と吐いた時それぞれで頭の角度が変わらないようにNeckとHeadで調整することです。

Etc

Inhale Method
吸気時のイージングメソッドを変更できます。基本的には初期値の"Ease Out Sine"を推奨しますが、気に入らない時は"Ease In Out Quad"を試してみてください。
なお、排気時のイージングメソッドは"Ease In Out Quad"固定となっており変更できません。

最後に

いつものごとく、ユニティちゃんのライセンスを張っておきます。

ユニティちゃんライセンス

このコンテンツは、『ユニティちゃんライセンス』で提供されています