コードを拝見しますにGetWorldPose
で取得したrotationFL
を使用せずに独自に回転を求めていらっしゃるように見受けられますが、WheelCollider
自体は回転しないでしょうから、タイヤの回転を正しく求めるにはrotationFL
も組み合わせる必要があるんじゃないでしょうか?
Standard Assetsに収録されている車の例の構造をベースに、下記のように簡略化したスクリプトで車をコントロールしたところ...
C#
1using System;
2using UnityEngine;
3
4public class CamberedWheelCar : MonoBehaviour
5{
6 [SerializeField] private Axle[] axles;
7 [SerializeField][Min(0.0f)] private float downforce = 200.0f;
8 [SerializeField][Min(0.0f)] private float maxMotorTorque = 400.0f;
9 [SerializeField][Range(0.0f, 90.0f)] private float maxSteeringAngle = 30.0f;
10
11 private float motor;
12 private new Rigidbody rigidbody;
13 private float steering;
14
15 private void Start()
16 {
17 this.rigidbody = this.GetComponent<Rigidbody>();
18 }
19
20 public void FixedUpdate()
21 {
22 var velocity = this.transform.InverseTransformDirection(this.rigidbody.velocity);
23 this.motor = this.maxMotorTorque * Input.GetAxis("Vertical");
24 this.steering = this.maxSteeringAngle * Input.GetAxis("Horizontal");
25 foreach (var axle in this.axles)
26 {
27 if (axle.steering)
28 {
29 axle.leftCollider.steerAngle = this.steering;
30 axle.rightCollider.steerAngle = this.steering;
31 }
32
33 if (axle.motor)
34 {
35 axle.leftCollider.motorTorque = this.motor;
36 axle.rightCollider.motorTorque = this.motor;
37 }
38
39 // WheelColliderからワールド空間上の位置・回転を取得したのち...
40 axle.leftCollider.GetWorldPose(out var leftPosition, out var leftRotation);
41 axle.rightCollider.GetWorldPose(out var rightPosition, out var rightRotation);
42
43 // 通常であればそれをそのままタイヤのモデルに適用するところを...
44 /*
45 axle.leftModel.SetPositionAndRotation(leftPosition, leftRotation);
46 axle.rightModel.SetPositionAndRotation(rightPosition, rightRotation);
47 */
48
49 // WheelCollider自体は車体に対して回転していないので、タイヤが向いているワールド方向はこうなり...
50 var leftWheelForward = axle.leftCollider.transform.TransformDirection(Quaternion.Euler(0.0f, axle.leftCollider.steerAngle, 0.0f) * Vector3.forward);
51
52 // それを軸にキャンバー角の分だけひねる回転を求める
53 var leftCamberRotation = Quaternion.AngleAxis(axle.camber, leftWheelForward);
54
55 // 右タイヤも同様にキャンバー回転を求める
56 var rightWheelForward = axle.rightCollider.transform.TransformDirection(Quaternion.Euler(0.0f, axle.rightCollider.steerAngle, 0.0f) * Vector3.forward);
57 var rightCamberRotation = Quaternion.AngleAxis(-axle.camber, rightWheelForward);
58
59 // WheelColliderによる回転の後でキャンバー回転を適用したいので、
60 // キャンバー回転を左側からかけた回転を求め、それをタイヤのモデルに適用する
61 axle.leftModel.SetPositionAndRotation(leftPosition, leftCamberRotation * leftRotation);
62 axle.rightModel.SetPositionAndRotation(rightPosition, rightCamberRotation * rightRotation);
63 }
64
65 this.rigidbody.AddRelativeForce(new Vector3(0.0f, this.downforce * Mathf.Abs(velocity.z), 0.0f));
66 }
67
68 [Serializable]
69 public struct Axle
70 {
71 public WheelCollider leftCollider;
72 public Transform leftModel;
73 public WheelCollider rightCollider;
74 public Transform rightModel;
75 [Range(-90.0f, 90.0f)] public float camber;
76 public bool motor;
77 public bool steering;
78 }
79}
下図のようにタイヤが傾きました。なお、見た目を傾けているだけでWheelCollider
自体は直立したままですから、キャンバー角に応じた車高の沈み込みや挙動の変化は別途調整する必要があるかと思います。
また、ブレーキのパーツの配置については考慮していませんが、こちらも同じくタイヤの前方を軸とするキャンバー回転を適用することでタイヤに沿って傾けることができるんじゃないかと思います。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2022/04/05 16:34