Google+ もご覧ください
ユーザーアイコン

Unityではじめるゲーム開発

Unity 4.5 で追加された Wheel Joint 2D の使い方

Nakamura001

Unity 4.5 で追加された Wheel Joint 2D の使い方

実は前回までで2Dの物理処理関連のコンポーネントの解説は終わる予定でした。しかし、 Unity 4.5 でもう1つ Wheel Joint 2D という車やバイクなどの車輪の物理シミュレーションを行うコンポーネントが追加されました。そのため、予定を変更して 4.5 で新しく追加された Wheel Joint 2D の使い方の解説を行います。

今回も実際に手を動かして貰いながら解説を進めます。こちらのプロジェクトを事前にダウンロードして開いておいて下さい。

完成させるものを確認

事前に完成させるものを確認しておきましょう。 Complete シーンを開いて、カーソルキーの左右で操作してみて下さい。 Reset ボタンを押すと車が最初の位置に戻ります。

完成画面
完成画面

今回は Wheel Joint 2D を使ってこのような車を作成します。

車体と車輪を配置

それでは作成を開始しましょう。 Start シーンを表示し、Project ビューの Textures フォルダにある Body をジャンプ台の前に配置し、 Rigidboy 2DPloygon Collider 2D を追加して下さい。続いて、 Wheel を配置し、 Rigidboy 2DWheel Joint 2DCircle Collider 2D を追加します。 Circle Collider 2D はデフォルトでは実際の画像に比べてちょっと大きめになっているので Radius の値を 0.675 に変更しておきましょう。

ここまで作業を行った Wheel は複製して2つにしておきます。これは前輪と後輪に使うので前輪FrontWheel後輪RearWheel という名前に変更した後に前輪と後輪の位置へ移動して下さい。

車輪に追加するコンポーネントは Wheel Joint 2D だけで良さそうな気もしますが Wheel Joint 2D だけでは当たり判定を行ってくれないので、別途当たり判定用の Collider を追加する必要があるためこのような構成となっています。

車関連のオブジェクトを整理するために空のオブジェクトを作成し、 Car という名前に変更した後に Body や Tire などをこのような階層構造にしておきましょう。

階層構造
階層構造

車体と車輪は車らしい配置になるように位置を調整し、地面よりちょっと浮かした位置に配置して下さい。

車体と車輪を繋げる

FrontWheel を選択、インスペクターから Wheel Joint 2DConnected Rigid BodyBody を設定します。

 Connected Rigid Body に Body を設定
Connected Rigid Body に Body を設定

RearWheel も同様に Body を設定して下さい。

Unity 4.3 の頃は 4.5 とは異なり、このように Joint 関連のコンポーネントで他のオブジェクトと接続を行った場合にどの位置で接続したかの情報は画面上に存在しませんでした。そのため、接続情報を画面に表示するには自分で別途処理を追加する必要が有りました。しかし、 4.5 からは接続情報が緑色のラインで表示される様になり、そのような作業が必要なくなりました。

試しに FrontWheel を選択してみるとこのように車輪の中心と車体の中心とが繋がりが緑色の線で表示されており、一目で接続位置を確認できます。

接続位置
接続位置

同様に RearWheel も確認してみて下さい。こちらも FrontWheel と同様に車体の中心に繋がっている事が確認できるはずです。

Wheel Joint 2D のプロパティ Anchor では自分自身(車輪)の接続位置を中心からの相対座標で指定します。 Connected AnchorConnected Rigid Body で指定したオブジェクト(今回の場合は車体)からの相対位置での接続位置指定となります。

今回は自身が車輪、接続先オブジェクトが車体になっていて、それぞれに指定した接続位置がデフォルトの (0, 0) のままなのでそれぞれの中心位置で繋がることになります。この辺りのルールは以前解説した Slider Joint 2D と同じです。

とりあえず、この状態で実行してみましょう。

するとこのような状態になったはずです。

実行結果
実行結果

ここでも Slider Joint 2D と同ような動作になっている事が確認できます。つまり、車輪の中心と車体の中心がバネ(スプリング)で繋がれているいるような動作です。

この結果から Connected Anchor で指定したオブジェクト(車体)と自身(車輪)の間には2つを繋ぐバネ、つまり車のサスペンションができていることが分かります。

そこでこの値を実際の車のサスペンションを再現できる位置に移動させます。

ここで注意しないといけないのは Wheel Joint 2D や Spring Joint 2D ではバネを再現してはいますが実際のバネとは異なり、バネ自体は存在していません。

現実世界ではバネに繋がった2つのオブジェクトはバネが縮んだ距離より近づくことはありませんが、 Wheel Joint 2D や Spring Joint 2D はバネ自体は再現されていないため(※ Slider Joint 2D を追加すれば再現可能)、 Unity 上では2つのオブジェクトは距離がゼロになるまで近づきます。

言葉だけだと違いが分かりづらいと思うで実際に Unity 上でどのような動作になるのか確認してみましょう。2つの車輪の Connected Anchor の値を調整して以下のようにサスペンション(バネ)分のサイズを取るイメージで車輪の少し上の位置に設定して下さい。

 Connected Anchor の設定
Connected Anchor の設定

この状態で実行してみるとこのような状態になります。

実行結果
実行結果

実行前の位置より上の位置で車輪が止まっているのが確認できます。これが2つのオブジェクトは距離がゼロになるまで近づくと説明した動作になります。

このような動作となるため Connected Anchor は実際のサスペンションのイメージとは異なりますが車輪の中心と同じ位置に設定すると自然な動作にできます。

以下のように車輪の中心は車体の端になるように設定し、 Connected Anchor はその車輪の中心と同じ位置になるように変更して下さい。

 Connected Anchor の設定
Connected Anchor の設定

この状態で実行するとサスペンションが上手く再現されているのが確認できるかと思います。 Scene ビューで Car を移動させて高い位置から落として動作を確認してみて下さい。

車を動かす

車輪を回転させる処理は Wheel Joint 2D に用意してあるのでそれを使いましょう。具体的には Motor という部分です。2つの車輪の Use Motor にチェックを付け、 Motor の設定の部分を以下のように設定します。

 Motor の設定
Motor の設定

また、サスペンションの反応を良くするために SuspensionFrequency20 に変更しておきます。

車体と車輪の重さも調整しておきましょう。 Inspector でそれぞれの Rigidbody 2DMass の値を以下のように変更して下さい。

  • Body : 7
  • FrontWheel : 0.1
  • RearWheel : 0.3

この状態で実行すると自動的に右側に走って行くはずです。

車を操作する

次にユーザの入力により操作できるように処理を追加しましょう。

CarControl という名前で C# スクリプトを作成し、以下の内容を記述して下さい。このコードでは先ほどは固定で指定していたモーターの速度( Motor Speed )をユーザの入力を反映して指定するプログラムになっています。

using UnityEngine;
using System.Collections;

public class CarControl : MonoBehaviour {
    public GameObject body;
    public Rigidbody2D rigidFrontWheel;
    public Rigidbody2D rigidRearWheel;
    WheelJoint2D wjFrontWheel;
    WheelJoint2D wjRearWheel;
    Vector3 defualtPosition;

    void Start () {
        defualtPosition = body.transform.position;
        wjFrontWheel = rigidFrontWheel.gameObject.GetComponent<WheelJoint2D> ();
        wjRearWheel = rigidRearWheel.gameObject.GetComponent<WheelJoint2D> ();
    }

    void FixedUpdate () {
        float speed = Input.GetAxis("Horizontal") * 500.0f;
        JointMotor2D jm;
        jm = wjFrontWheel.motor;
        jm.motorSpeed = speed;
        wjFrontWheel.motor = jm;

        jm = wjRearWheel.motor;
        jm.motorSpeed = speed;
        wjRearWheel.motor = jm;
    }

    void OnGUI () {
        if (GUI.Button(new Rect(5, 5, 100, 30), "Reset")) {
            body.transform.position = defualtPosition;
        }
    }
}

この C# スクリプトを Car にドラッグして追加した後、 Inspector で以下のようにそれぞれのプロパティに対応するものをドラッグして設定して下さい。

  • Body : Body
  • Rigid Front Wheel : FrontWheel
  • Rigid Rear Wheel : RearWheel

この状態で実行するとカーソルキーで車を操作できます。

現状は問題有り

普通に走りますし、一見ちゃんと動作しているように見えますが実は問題点があります。

それではその問題点を確認してみましょう。まずは前輪と後輪の重さを合わせるために RearWheelRigidbody 2DMass の値を 0.1 に変更しておきましょう。これで前輪と後輪の重さが同じになったので車を高い位置から落とすとサスペンションの反発力で垂直に跳ね返るはずです。

RearWheel を選択し、Gizmoが表示されている状態にします。その状態のままゲームを実行し、車輪の上に描画されている緑色の線が斜めになるような位置まで車をバックして下さい。

車輪の緑色の線が斜めに
車輪の緑色の線が斜めに

この状態で Scene ビューCar を掴んで持ち上げた後、離して地面に落下させて下さい。すると斜め後ろの(画面の左上)方向に跳ねるのが確認できるはずです。

車輪の上に描画されている緑の線はサスペンションの向きを表しています。そのため、先ほど状態ではサスペンションは斜めに配置された状態となっていました。その状態で地面に向けて落としていたため、車は斜め後ろに向けて跳ねるという動作となりました。

また、現在の状態では車を操作すると車輪が回転するのに合わせてサスペンションも回転してしまっていることも確認できたはずです。

という事で、現在の状態だとサスペンションの向きが斜めになっているタイミングでジャンプ台から地面に着地した時などに妙な挙動をしてしまいます。

この症状を改善するためにサスペンションの向きは常に車体に対して垂直になるようにプログラムしておく必要が有ります。早速、そのプログラムを追加する事にしましょう。

サスペンションの向きを常に垂直に

CarControl の FixedUpdate () ブロックの前に以下の記述を追加して下さい。

    void Update () {
        JointSuspension2D suspension;
        suspension = wjFrontWheel.suspension;
        suspension.angle = 90f-rigidFrontWheel.transform.eulerAngles.z+body.transform.eulerAngles.z;
        wjFrontWheel.suspension = suspension;

        suspension = wjRearWheel.suspension;
        suspension.angle = 90f-rigidRearWheel.transform.eulerAngles.z+body.transform.eulerAngles.z;
        wjRearWheel.suspension = suspension;
    }

ここでは車体と車輪の角度を元に常にサスペンションが車体に対して垂直(90°)になるようにしています。この処理を追加した状態でジャンプ台を飛んでみると奇妙な跳ね返りが起こることもなく、着地できたはずです。

最後に

これで Wheel Joint 2D による車の制御は完成です。車の代わりにバイクに変えても良いですし、現在の様にリアルな挙動を目指すのではなく、勢い良くジャンプするようにパラメータを調整したり、車輪に Physics Material 2D を追加して滑りやすかったり、弾みやすかったり、タイヤの特性を変えてみるのも良いでしょう。

今回解説した内容が理解できていれば後は簡単に発展させていくことが出来るかと思います。是非、ここで学んだことを元にレースゲームなどを作ってみて下さい。

Unity
タグ:

記事をリクエストする

関連記事

コメント