-100p

-10p

+10p

+100p

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つにアタッチ。

以下それぞれのComponentの解説。

Rigidbody2D


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

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

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


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

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

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

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

0
0

-100p

-10p

+10p

+100p