前回までの本編は、Mecanimを使ったユニティちゃんの制御を行いました。 今回はMecanimから離れて、物理エンジンを使った揺れ物の制御を行っていきましょう。
なお今回も前回までのUnityプロジェクトを引き続き使用します。
頭のリボンを物理演算で揺らす -リジッドボディ、ジョイント-
ユニティちゃんの頭に付いているリボン。今のままでは走っても止まってもビクともしません、とても固そうです。これに物理エンジンでそれらしい動きをつけましょう。
物理エンジンを用いてこれを表現するには、リジッドボディ と ジョイント を用います。 それぞれ、「剛体としての性質」、「他のオブジェクトとの連結」を設定するものです。
オブジェクト階層構造を変更する
物理演算を使うときは下準備として、まずオブジェクトの階層構造を物理演算に適したものに変えなければいけません。
物理的に干渉してほしいオブジェクト同士は、親子であってはいけません。親が移動しても、子の相対的な位置が変わらないからです。相対的な位置が変わらないということは、親と子がぶつかったり引っ張り合ったりと言うことは起きず、思ったように動いてくれません。
まずは、重力などの物理的な影響を受けてほしい部分とそうでない部分を切り分けましょう。
上図はまだ手を付けていないユニティちゃんです。 Character_Reference というオブジェクトに連なっているのは、すべてボーンと呼ばれる骨組みです。対して mesh_root に連なっているのは、ボーンによって制御されるメッシュ(肌のようなもの)です。
切り分けると下図のようになります。physical_bone という GameObject を作成して、リボンの根から下にあるボーンをすべてこれの下に移動しましょう。この時、ボーンは必ず unitychan オブジェクトより外の階層に移動させてください。ユニティちゃんが歩くことによって移動するのはこの unitychan オブジェクトなので、このオブジェクトの子になっていてはいけません。
また、リボンのボーンそれぞれの親子関係も解消しましょう。基本的には物理的な影響を受けるオブジェクトの下に、物理的な影響を受けるオブジェクトを置かないということを徹底します。
オブジェクトに物理演算を適用する -リジッドボディ-
リボンをユニティちゃんから切り離しました。次はこれに物理演算が適用されるようにしましょう。
オブジェクトに剛体としての性質を付与するのが リジッドボディ です。すべてのリボンのボーンに Rigidbody を追加しましょう。リボンのボーンをすべて選択して、[Component] -> [Physics] -> [Rigidbody] で追加することができます。
リジッドボディに設定できる主なパラメータは以下のようになっています。
Mass | 重さ。単位はkg。 |
Drag | 空気抵抗。Infinityを設定すると慣性が働かなくなります。 |
Angular Drag | 回転に対する空気抵抗。Infinityを設定すると回転に対する慣性が働かなくなります。 |
Use Gravity | 重力の影響をうけるか。 |
Is Kinematic | あらゆる外部からの物理的影響を受けなくするか。 |
今回は、すべてのボーンのリジッドボディの Mass を 10 に設定します。実際にはこんなに重いはずがありませんが、ゲームで物理エンジンを使うときは現実的な値を入れることよりも、結果としてそれらしい動きをする値を入れるのがコツです。
また、後述するジョイントのために、リボンの根( unitychan\Character1_Reference\Character1_Hips\Character1_Spine\Character1_Spine1\Character1_Spine2\Character1_Character1_Neck\Character1_Head\J_*_HeadRibbon_00) にもそれぞれリジッドボディを設定します。こちらは外部からの力の影響を受けてほしくないので、Use Gravity のチェックを外し、Is Kinematic のチェックを入れておきましょう。
これでリジッドボディの設定が終わりました。
オブジェクトを連結する -ジョイント-
リボンに物理演算を適用出来ました。しかしこのままでは、衝突と連結の設定をしていないため、全てをすり抜けて、ただ落下していきます。
次は ジョイント を使ってリボンの付け根とリボンのボーンを連結し、互いに引っ張りあえるようにします。
ジョイントを連結する
ジョイントは、リボンのボーンをすべて選択して [Component] -> [Physics] -> [Character Joint] で追加することができます。ジョイントには種類がいくつかありますが、今回はこの Character Joint を利用します。
ジョイントは、それぞれにそれぞれの連結先のリジッドボディを設定する必要があります。 Character Joint の Connected Body に、それぞれの連結先(根)となるオブジェクトを設定しましょう。リボンのボーンは 名前の連番が若い方がそれぞれの根になるように設定してください。
これでジョイントでの連結が終わりました。
ジョイントのパラメータを設定する
ここまでくると、やっとリボンがそれらしい動きをするようになってきました。しかしまだ可動域が広すぎて垂れてしまっています。次はジョイントの可動域を指定して、リボンの曲がりにくさを設定しましょう。
ジョイントに設定できるパラメータはジョイントの種類によってまちまちですが、代表的なものとしては、可動軸、可動域を設定するパラメータ、可動域を超えた場合の反動や弾みを設定するパラメータ、ジョイントが引き戻そうとする力に対する減衰のパラメータがあります。
例えば、Character joint には以下の様なパラメータがあります。
Axis | ねじれ軸。ジョイントがねじれ曲がる軸の向き。基本的にはジョイントの根に向けて設定します。 |
Swing Axis | 折れ軸。ジョイントが折れ曲がる軸の向き。(蝶番のイメージする) |
Low Twist Limit.Limit | ねじれ軸に対して右回転のねじれの下限(単位は度) |
High Twist Limit.Limit | ねじれ軸に対して右回転のねじれの上限(単位は度) |
Swing 1Limit.Limit | 折れる曲がる角度の限界。許容する角度の絶対値。 |
Swing 2Limit.Limit | ねじれ軸と折れ軸に直角なもうひとつの軸に対する、曲がりを許容する角度の絶対値。 |
今回は以下のように設定しましょう。
オブジェクト | Axis | Swing Axis | Low Twist Limit.Limit | High Twist Limit.Limit | Swing 1Limit.Limit | Swing 2Limit.Limit |
J_L_HeadRibbon_01 | 1, 0.5, 0.5 | -1, 1, 0 | -5 | 5 | 20 | 20 |
J_L_HeadRibbon_02 | デフォルト | デフォルト | 〃 | 〃 | 〃 | 〃 |
J_R_HeadRibbon_01 | 1, 0.5, -0.5 | -1, 1, 0 | 〃 | 〃 | 〃 | 〃 |
J_R_HeadRibbon_02 | デフォルト | デフォルト | 〃 | 〃 | 〃 | 〃 |
お疲れ様です。これで全ての設定が終わりました。実行して 1キー を押してみましょう。
リボンがいい感じに揺れました!!
歩いている分にはいいのですが、走った時にリボンがガクガクしてしまいます。これは Unity がゲームループと物理演算を非同期で行っていることによる仕様で、等速運動する物体とジョイントの相性が非常に悪い のです。どうしても気になる場合は、以下のスクリプトを任意のオブジェクトに適応し、物理演算の間隔をゲームループの間隔に近づけましょう。(それでも物理演算のタイミングと画面の更新タイミングの問題で、リボンが伸びてしまいますが、さすがにこれは仕方がありません。こだわりたい方は、ユニティちゃんv1.2に付属する SpringManager.cs などを参考に、スクリプトで物理挙動をシミュレーションするとよいでしょう。)
using UnityEngine; using System.Collections; public class TimeStepAutoConfigurator : MonoBehaviour { void Update(){ Time.fixedDeltaTime = Time.deltaTime; } }
おまけ
同様に髪の毛に物理演算を適用するとこのようになります!ぜひチャンレジしてみてください。
おわりに
今回は リジッドボディ と ジョイント を使って揺れものの制御を行いました。
次回はまた違う機能(と少々スクリプト)を使って、ユニティちゃんを更にブラッシュアップします。お楽しみに!