質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

Q&A

解決済

2回答

3057閲覧

【wheelcollider】Unityで回転軸、向きを指定してタイヤを回転させたい

pleiades634

総合スコア5

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

0グッド

0クリップ

投稿2022/04/04 02:21

困っていること

Unity、およびC#を利用して、レースゲームの制作をしています。

現在、車体の前方から見たときにタイヤがハの字になるように角度をつけたいと考えているのですが、その際に自然に回転させることに苦労しています。イメージ画像
(↑イメージ画像)

なお、使用しているエディタは2020.3.0f1です。

試したこと

※現状、左フロントタイヤのみを使ってあれこれ試行錯誤しています。以下のコードも左フロントタイヤに関する記述を抜き出したものになります。

タイヤのハの字の角度、ハンドルの舵角、車体の向きから定義した回転軸と、左フロントタイヤに割り当てたwheelcolliderから抽出した回転量をQuaternion.AngleAxis()に代入しました。また、ブレーキのパーツも回転軸の方向を向いていてほしいのでそのような設定しています。

c#

1void Update() 2 { 3 Vector3 FCamberVector = new Vector3(0, Mathf.Tan(FrontCamber*Mathf.Deg2Rad), 0); 4 Vector3 LSteerVector = Mathf.Tan(leftsteering*Mathf.Deg2Rad) * car.up; 5 Vector3 FLDriveaxis = car.right + FCamberVector + LSteerVector; 6 7 brakeFLTrans.forward = -FLDriveaxis; 8 wheelFLTrans.right = FLDriveaxis; 9 10 float FLAngle = wheelFL.rpm / 60 * 360 * Time.deltaTime; 11 12 wheelFL.GetWorldPose(out Vector3 positionFL, out Quaternion rotationFL); 13 brakeFLTrans.position = positionFL; 14 Quaternion FLrot = Quaternion.AngleAxis(FLAngle, FLDriveaxis); 15 wheelFLTrans.rotation = FLrot * wheelFLTrans.rotation; 16(以下略)

その結果次のような挙動を示しました:
イメージ説明

タイヤの回転軸は狙い通りに設定できている上に、向きも申し分ないのですが、うまく回転しません。

上のコードから、wheelFLTrans.right = FLDriveaxis; の文を取り除くと次のような挙動を示します:
イメージ説明
今度は回転こそするものの、回転軸に対してタイヤの向きが定まらず、不自然な挙動を示してしまいます。

まとめ

現在の目標としては1枚目のgif画像の状態で滑らかにタイヤを回転させることになります。どこで不具合が生じているのか見当がつかないので、どなたか助言いただければ幸いです。よろしくお願いいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

コードを拝見しますに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/04 21:11

Bongo

総合スコア10807

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

pleiades634

2022/04/05 16:34

ありがとうございます! こちらの方法でうまく動作しました。
guest

0

一応私の方でも解決方法を見つけたのでメモ程度に記しておきます。

ブレーキのパーツを狙い通りの方向を向かせることには成功していたので、このウェブサイト(https://nekojara.city/unity-rotate-axis)
を参考にして、タイヤのモデルをブレーキのパーツの子オブジェクトとして設定し、ローカル空間で回転させることで解決を図りました。

タイヤをブレーキの子オブジェクトに設定したところ、ホイールコライダーが正常に動作しなくなったため、レンダリングをしないダミーのホイールを追加し、元々あったタイヤのモデルと置き換えました。

イメージ説明

上のgif画像の通り、目標通りの動きとなっています。

...しかし、コードがかなり煩雑になり、あまり良い解決策とは思えないので、Bongoさんの回答をベストアンサーにさせていただきたいと思います。

投稿2022/04/05 05:18

pleiades634

総合スコア5

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問