Unityでチェーン揺れの実装

Unityでチェーン揺れの実装

Unityでチェーン揺れなど揺れ物の実装。Rigidbody2D、HingeJoint2D、FixedJoint2Dの使い方。

関連ページ
参考URL
Unityは非常に高機能で、例えばキーホルダーのチェーン揺れなど揺れ物の実装したい時も、既に専用のComponentが用意されています。
一度慣れてしまえば簡単に実装できるものの、最初は混乱するためこのページではその解説をしたいと思います。

ちなみに揺れ物をスクロール内部に置くと、実装の難易度が跳ね上がります。
かなり厄介なので 次のページ で分けて解説します。

揺れ物実装の概要

Unityで揺れ物を実装するには、
最低限
Rigidbody2D
HingeJoint2D
FixedJoint2D
の3つのComponentが必要になります。

次の動画は全ての実装を終えた場合の挙動です。

このような結果に至るまでは、結構色々な手順を踏む必要があります。

Rigidbody2D、HingeJoint2Dをアタッチ

まず揺れ物を構成する全てのGameObjectに
Rigidbody2D
HingeJoint2D
をアタッチします。
今回の場合Hook、Chain_1、Chain_2、Chain_3、Chain_4、Frameの6つにアタッチしています。
Rigidbody2DとHingeJoint2Dのアタッチ例
以下それぞれのComponentの解説になります。

Rigidbody2D

Rigidbody2Dのインスペクター
Rigidbody2D
はuGUI上で物理演算の実装をするのに必須なComponentです。
Unityではシーンの全てのGameObjectに重力を与える方法と、それぞれのGameObjectに個別の重力を当たる方法があります。
Rigidbody2Dをアタッチするごとで個別に重力を設定できます。

重要なのは
Mass
LinearDrag
AngularDrag
GravityScale
の4つです。
 Mass 
: 質量の値。低いものは動き易く落下が緩やかに、高い物は動き難く落下が急速になる。
 LinearDrag 
: 位置移動の減衰値。低いと揺れが収まり難く、いつまでも揺れる。高いとそもそも動かなくなる。
 AngularDrag 
: 回転移動の減衰値。低いと揺れが収まり難く、いつまでも揺れる。高いとほとんど揺れなくなる。
 GravityScale 
: 重力の度合い。低いと落下が緩やかに、揺れが収まり難くなる。高いと落下が急速に、揺れが収まりやすくなる。
目指す揺れの演出を作る際に、この4つパラメータは目的が一部被っていて、それでいて微妙に効果が違かったりします。
繊細微妙なパラメータ調整が必要になります。

HingeJoint2D

HingeJoint2Dのインスペクター
RigidbodyとRigidbodyを連結させ、繋げた2つの動きにある程度相関関係を持たせます。
連結の仕組みは一方通行で、連結する側の座標移動に対して円運動のような変換が行われます。

HingeJoint2Dはアタッチした初期状態からほとんど変える必要がないです。
ただ一点、
ConnectRigidBody
に、連結するRigidbody2Dを指定する必要があります。
アタッチは、下から上に隣接するRigidbodyに対して行います。
例えばFrameに対してはChain_4を、Chain_4に対してはChain_3をアタッチしています。

一番上のHookに関しては、ConnectRigidBodyはNoneのままで良いです。

これによってHookのみ、誰にも依存せず空間上に固定されます。

AddForceで揺れ物を動かす

本格的な揺れ物を作るにはあと
FixedJoint2D
の実装が必要ですが、一旦ここまでの段階でC#から揺れ物を動かしてみます。
以下実装したUnity C#の全文です。
using UnityEngine;
using UnityEngine.UI;

public class TestChain : MonoBehaviour
{
    [SerializeField]
    private Button button;
    [SerializeField] 
    private Rigidbody2D swayTarget; 
//力を加える対象


    [Space(10)]
    [SerializeField] 
    private float pow = 2000; 
//力の大きさ


    private void Start()
    {
        
//スクリプトからボタンイベントを登録

        button.onClick.AddListener(DoSway);
    }

    
/// <summary>

    
/// swayTargetに対して力を加える

    
/// </summary>

    private void DoSway()
    {
        swayTarget.AddForce(Vector2.right * pow);
    }
}
swayTarget
には一番下のFrameのRigidbody2Dをアタッチ。
登録したボタンを押すたびに、swayTargetに対して右方向にVector(2000, 0, 0)の力を加えます。
実装の結果は次の通り。

概ね実装できてますが、一番下のRigidbody2DのFrameのrotationが何かおかしい。

FixedJoint2Dをアタッチ

rotationを修正するには、
FixedJoint2D
をアタッチします。
空間上に固定されたHookのみアタッチの必要がなく
、それ以外のChain_1、Chain_2、Chain_3、Chain_4、Frameにアタッチします。

各GameObjectのComponentのアタッチ状況は次の通りです。
 Hook 
: Rigidbody2D、HengeJoint2D
 Chain_1 
: Rigidbody2D、HengeJoint2D、FixedJoint2D
 Chain_2 
: Rigidbody2D、HengeJoint2D、FixedJoint2D
 Chain_3 
: Rigidbody2D、HengeJoint2D、FixedJoint2D
 Chain_4 
: Rigidbody2D、HengeJoint2D、FixedJoint2D
 Fook 
: Rigidbody2D、HengeJoint2D、FixedJoint2D

FixedJoint2D

FixedJoint2Dのインスペクター
HingeJointと同様、
ConnectRigidBody
には下から上へ隣接するRigidbodyを指定します。
これによって、連結する側のrotationが、常に連結される側の方向を向くように固定されます。

この段階での実装の結果は次の動画の通りです。

ガチガチに動きが固まって揺れ物感がなくなってしまっています。

修正のためChain_1、Chain_2、Chain_3、Chain_4にアタッチした
FixedJoint2D
に関しては、
Frequentry
の値を2あたりを指定してみます。
 Frequency 
: スプリングの振動頻度。低いほど柔らかく、高いほど固くなるが、例外的に最低値の0にすると完全にスプリングが固まる。

これで実装完了です。
0
0