車を走らせる(Wheel Collider)

Wheel Colliderの基本

車のゲームを作るには、基本的な車の機能を持つコライダー、Wheel Colliderの公式ドキュメントを確認しつつ進めます。

簡単なブロックの車を作る前に、地面を

GameObject > 3D Object > Terrain

で作成しておきます。

1. 公式ドキュメントより「基本的な車のスケルトンの作成

ここは公式ドキュメント通りで問題なかったです。ただし、以下注意です。

メッシュコライダーについての注意(covexのところ)

https://docs.unity3d.com/ja/2018.4/Manual/class-MeshCollider.html

2. 「タイヤ」を使った、より具体的な見せ方

子供の頃作った「積み木の車」のようなもので、タイヤが回転し、前輪が左右に方向が変わるようにしたいと思います。

[car_mokei.mp4](%E8%BB%8A%E3%82%92%E8%B5%B0%E3%82%89%E3%81%9B%E3%82%8B%EF%BC%88Wheel%20Collider%EF%BC%89%200416d51e05ac45f18a3f78da15268d27/car_mokei.mp4)

公式ドキュメントにはこうあります。

Wheel Collider はシミュレーションしたホイール位置と回転を Wheel Collider の Transform には適用しません。そのため、視覚的なホイールを追加するには、いくらか工夫が必要です。

最初に、タイヤのオブジェクトを追加します。その際に以下のような階層構造になるようにします

frontLeft Wheel Coliderが追加されたオブジェクト。
GameObject 空のゲームオブジェクト
Cylinder 3Dオブジェクト > Cylinder

次にコードを修正します。公式ドキュメント通りで大丈夫です。

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

[System.Serializable]
public class AxleInfo {
    public WheelCollider leftWheel;
    public WheelCollider rightWheel;
    public bool motor;
    public bool steering;
}
     
public class SimpleCarController : MonoBehaviour {
    public List<AxleInfo> axleInfos; 
    public float maxMotorTorque;
    public float maxSteeringAngle;
     
    // 対応する視覚的なホイールを見つけます
    // Transform を正しく適用します
    public void ApplyLocalPositionToVisuals(WheelCollider collider)
    {
        if (collider.transform.childCount == 0) {
            return;
        }
     
        Transform visualWheel = collider.transform.GetChild(0);
     
        Vector3 position;
        Quaternion rotation;
        collider.GetWorldPose(out position, out rotation);
     
        visualWheel.transform.position = position;
        visualWheel.transform.rotation = rotation;
    }
     
    public void FixedUpdate()
    {
        float motor = maxMotorTorque * Input.GetAxis("Vertical");
        float steering = maxSteeringAngle * Input.GetAxis("Horizontal");
     
        foreach (AxleInfo axleInfo in axleInfos) {
            if (axleInfo.steering) {
                axleInfo.leftWheel.steerAngle = steering;
                axleInfo.rightWheel.steerAngle = steering;
            }
            if (axleInfo.motor) {
                axleInfo.leftWheel.motorTorque = motor;
                axleInfo.rightWheel.motorTorque = motor;
            }
            ApplyLocalPositionToVisuals(axleInfo.leftWheel);
            ApplyLocalPositionToVisuals(axleInfo.rightWheel);
        }
    }
}

そして最後、これがどこにも書いてなかったのですが、car_rootオブジェクトに付随するスクリプトのAxle Infosのパラメーターを繋ぎ直します。

Cylinderオブジェクトを追加し、スクリプトを変えた時点で、元々のパスが存在しないことになるので、当たり前なのですが、見落としました….

これで無事動くようになります!

足回りの調整

Riigidbodyの重心を変える

ジャンプしたジープが前のめりで落下する….重心を変えることで解決!

このCenter Of Mass のZ軸を0からわずかに下げることで、問題は解決した。

ちなみに、横転しやすさもY軸をわずかに下にすることで解決した!

サスペンションの可動域を広げた

サスペンションは、Sspension Distanceで広げた。ただし、Radius * 2 がタイヤの直径になるので、それを超えるとおかしくなるらしい。

あとForce App Point Distanceも少しだけ下げた。

ちなみに、カーブを曲がるときにスリップしやすかったのは、Forward FrictionとSideways Frictionのの設置値を変えることで良くなった! このパラメーターの理由が、なかなか難しい。

参考URL