4
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Life is Tech ! MentorsAdvent Calendar 2024

Day 9

Unityでリアルな車の挙動を簡単に作ろう!

Last updated at Posted at 2024-12-08

はじめに

こんにちは!
Life is Tech ! Advent Calendarの9日目を担当するGeekです!
私がF1をはじめとしたモータースポーツオタクなのは、みなさんご存知かと思います。
昨日、F1とSUPER GTの2024シーズンも終了してしまいました...

さて、そんな私はかれこれ5年間、Unityでレースゲームを作り続けています。
大学のAO入試でもレースゲームを提出し、卒業制作でもレースゲームを制作しています。
そこで、今回は誰でも簡単に出来るWheel Colliderを用いた車の挙動づくりをご紹介します!

この記事の意義

「いや、僕私、レースゲーム作らないんですけど...」と思った方も多いかもしれません。
しかし、ゲームにおける車ってレースゲームにしか登場しないものでしょうか?
思い出してみると、シューティングゲーム、特にバトルロワイヤルゲームにはよく登場しませんか?
あの挙動を、Wheel Colliderを活用することで簡単に実現できます!
車が簡単に実装できれば、作れるゲームの幅の広がるかもしれませんね!

目指すもの

キーボード操作で運転できる車を作ろう!
画面収録 2024-12-09 1.36.13_5.gif

環境

Unity 6000.0.25f1

Wheel Colliderとは

Wheel Collider は、陸上車両用の特殊なコライダーです。組み込み衝突検出、ホイール物理特性、スリップベースのタイヤ摩擦モデルを含みます。ホイール以外のオブジェクトにも使用できますが、特にホイールのある車両向けに設計されています。
Unity Documentationより

要するに、車やバイクの駆動、タイヤ、サスペンションとかをシミュレートできるコライダーだよ!ということです。

Wheel Colliderの使い方

それでは早速実装方法をご紹介します!
このWheel Collider、他のコンポーネントにはない複雑な使い方をします。
まずはじめに、車を構成するゲームオブジェクトの親子関係を箇条書きで示します。

  • Car(空でも可)
    • CenterOfMass(車の重心を決めるための空のオブジェクト)
    • Body(車のボディの見た目)(Positionはすべて0)
    • Wheels(Wheel Colliderがアタッチされているゲームオブジェクトを子に持つ親)(Positionはすべて0)
      • Front Right(右前タイヤ)(Wheel Colliderをアタッチ)
        • Wheel Object(タイヤの見た目)
      • Front Left(左前タイヤ)(Wheel Colliderをアタッチ)
        • Wheel Object(タイヤの見た目)
      • Rear Right(後ろ右タイヤ)(Wheel Colliderをアタッチ)
        • Wheel Object(タイヤの見た目)
      • Rear Left(後ろ左タイヤ)(Wheel Colliderをアタッチ)
        • Wheel Object(タイヤの見た目)

実際の画面
スクリーンショット 2024-12-09 1.49.46.png

親オブジェクトについて

このオブジェクトにアタッチするのは、

  • Rigidbody
  • Box Collider
  • 車を制御するためのスクリプト
    の3つです。

Rigidbody

必ず調整しなければ行けない項目はMassのみです。
実際の車は1500kgほどが一般的ですので、Massは1500くらいが無難です。

Box Collider

CenterとSizeを調整して、車のボディが覆われるように設定してください。
この時、地面に接してしまわないように車の底部がColliderの底部になるよう調整してください。
シャコタンになってタイヤが接地しなくなります。
スクリーンショット 2024-12-09 1.53.50.png

車を制御するためのスクリプト

車の運転は、走る、曲がる、止まる。
もっと詳しく言うと、前進後退、右折左折、停止ができればOKです。
これを成業するためにWheel Colliderには

  • motorTorque(回転の力)
  • steerAngle(左右の舵角)
  • brakeTorque(ブレーキの力)
    という変数が用意されていて、これに値を代入すれば車が動きます。
    あとはInputの内容を値に反映してあげれば良いわけです。
    今回はWASDキーor矢印キーで前後左右の操作、スペースキーでブレーキという操作を前提にサンプルのスクリプトを用意しました。
サンプルコード
SampleCarController.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;

public class SampleCarController : MonoBehaviour
{
    private Rigidbody RB;
    [SerializeField] Transform CenterOfMass;
    //Rigidbody.centerOfMassを上書きして、車の重心を決めるためのTransform
    [SerializeField] WheelCollider[] Wheels;
    //Wheel Colliderがアタッチされている各タイヤ
    [SerializeField] Transform[] Obj;
    //タイヤの見た目(AwakeでWheelsから取得するため割当不要)

    [SerializeField] string XAxisName = "Horizontal";
    [SerializeField] string YAxisName = "Vertical";
    [SerializeField] KeyCode BrakeKey = KeyCode.Space;
    //前後移動はVertical、ハンドル操作はHorizontalで行う。(InputManager参照)

    [SerializeField] Vector2 InputVector;
    //キー操作を受け取る
    [SerializeField] float BrakeInput = 0;
    //ブレーキのキー入力を受け取る

    [SerializeField] float AccelPower = 1000f;
    //車のパワー
    [SerializeField] float HandleAngle = 45f;
    //最大でハンドルが切れるタイヤの角度
    [SerializeField] float BrakePower = 1000f;
    //ブレーキの力

    [SerializeField] float[] DriveWheels = new float[] { 0f, 0f, 1.0f, 1.0f };
    //駆動させるタイヤ。0なら駆動しない、1なら駆動する。(パワーでタイヤを回すかどうか。初期値は後輪駆動)
    [SerializeField] float[] SteerWheels = new float[] { 1.0f, 1.0f, 0f, 0f };
    //ハンドル操作で曲がるタイヤ。

    // Start is called before the first frame update
    void Awake()
    {
        Wheels = GetComponentsInChildren<WheelCollider>();
        RB = GetComponent<Rigidbody>();
        RB.centerOfMass = CenterOfMass.localPosition;

        Obj = new Transform[Wheels.Length];
        for (int i = 0; i < Wheels.Length; i++)
        {
            Obj[i] = Wheels[i].transform.GetChild(0);
        }
    }

    // Update is called once per frame
    void Update()
    {
        ControllInput();

        CarControll();
    }
    private void ControllInput()
    {
        InputVector = new Vector2(Input.GetAxis(XAxisName), Input.GetAxis(YAxisName));
        BrakeInput = Input.GetKey(BrakeKey) ? BrakePower : 0f;
    }

    private void CarControll()
    {
        for (int i = 0; i < Wheels.Length; i++)
        {
            Wheels[i].motorTorque = InputVector.y * DriveWheels[i] * AccelPower;
            Wheels[i].steerAngle = InputVector.x * SteerWheels[i] * HandleAngle;
            Wheels[i].brakeTorque = BrakeInput;

            Vector3 _pos;
            Quaternion _dir;
            Wheels[i].GetWorldPose(out _pos, out _dir);
            Obj[i].position = _pos;
            Obj[i].rotation = _dir;
        }
    }
}

これをアタッチし、以下のように値を設定してください。
スクリーンショット 2024-12-09 2.14.09.png

これで親オブジェクトの設定は完了です!

Wheel Colliderについて

まず、Front Right~Rear Leftのタイヤが置かれる位置に座標をセットしてください。

次は、四輪すべてに追加したWheel Colliderの設定項目です。
ここはサスペンションの硬さ、減衰力、タイヤの摩擦力などかなり専門的な領域です。
基本的にこの設定を守ってもらえれば、しっかりとした挙動の車になるかと思います。
4つのWheel Collider、すべて同じ値でOKです。
スクリーンショット 2024-12-09 2.18.42.png

強いて変わるとするなら、タイヤの見た目に応じてタイヤの半径が変わると思うので、Sceneビューを見ながらRadiusを調整してください。

実際のサイズに合わせる。

親オブジェクトのSample Car ControllerスクリプトにあるWheelsに上から順番に割り当ててください。

CenterOfMassについて

車の重心は中央よりちょっと上くらいがおすすめです。
親オブジェクトのSample Car Controllerスクリプトに割り当ててください。
スクリーンショット 2024-12-09 2.19.56.png

おしまい!

以上が、最もシンプルな車の挙動の実装方法です。
今回は初心者向けということで、Wheel Colliderの詳しい説明は省きましたが、気になる方は調べてみてください!
これでレースゲームを作る第一歩を踏み出せますので、まずはF1を観るところからはじめてみましょう。

今回お借りした3Dモデル
Mazda Miata MX-5 NA - Sketchfab

4
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?