カーチュートリアル(Unity3d)パート3/3ガイド

パート1
パート2

始める前に、C#で書き直したスクリプトを提供したいと思います。 JSのスクリプトの半分のため、C#で書き直すことにしました(私はC#に精通しています)。 ダウンロードする

また、初心者向けのプロジェクト「プロジェクト:サバイバルシューター」のプロジェクトのアクティブな「分析」、次のプレイリストビデオチュートリアル、サバイバルシューター用の追加ビデオチュートリアルがあります。 私は個人的にこのチャンネルの努力に感謝します。

このマニュアルの最後にあるビデオレビューでは、2つの実装された運転方法の例が比較されています。

それでは、ガイドの勉強を始めましょう。

パート3:ボンネットの下


3Dモデル、スクリプト、組み込みコンポーネントから作業マシンを組み立てる方法はすでに見ました。 また、パブリック変数と、それらを使用して車を微調整する方法についても知りました。

ここで、 Carスクリプトの操作の研究に焦点を当てます。

Car.jsスクリプトをダブルクリックして、コードエディターで開きます。

このスクリプトは、500行を超えるコードとコメント、および多くの変数と関数を備えているため、一見すると少し威圧的です。 絶望しないでください。 スクリプトは、各関数で実行される内容を示す意味のある名前を持つ比較的小さな関数を持つように構築されています。 また、コードには、コードの特定のセクションを説明するコメントがあります。

そのため、スクリプトスタディの「エントリ」ポイントから開始し、ガイドに従うことをお勧めします。 この場合、これらのエントリポイントは、 Start()Update()、 FixedUpdate()関数になります。

これらの「コア」関数はそれぞれ、他の関数を呼び出します。 したがって、 Start()関数で開始すると、関数が最初にSetupWheelColliders()関数を呼び出したことがわかります。 コード内でこの関数を見つけて、その機能を調べてから、 Start()関数に戻り、次のSetupCenterOfMass()関数に進みます。 このコードを調べることで、車の機能を理解できます。 将来的には、これらすべての機能を検討します。 コードの各行については説明しませんが、すべての機能を順番に学習します。

何を知る必要がありますか?


Unityでの作業は、組み込みコンポーネント、エディター、D&D機能などのおかげで、多くの点で簡単です。 車のチューニングは作業の半分です。Unityはモデルのインポート、 衝突コンポーネント、 レンダリング 、および物理学をオブジェクトの追加ボタンをクリックしてオブジェクトに追加できます

スクリプト内では、主にこれらのコンポーネントの操作に取り組みます。 あなたは確かに私たちが車に何が起こるかを決定するために使用する多くの計算と式に出くわすでしょう。 これはゲームをリアルにする必然的な部分です。たとえば、基本的な機能以上のことをしたいときにスクリプトを書くなどして、いくつかのロジックを設定する必要があります。 これらの式と計算は、コンポーネントで使用されます。

コードがまったく馴染みがなく、どこから始めればよいかわからない場合は、次の点に焦点を合わせ、どのように、どのように機能するかを検討するというアプローチを試すことができます。

リジッドボディ
ホイールコライダー
•計算と計算式、およびその順序。

このように考えてください:
リジッドボディを車のモデルに追加するとき、その物理的能力を制御する方法があります。 これを行うには、前方に移動する力を計算し、速度を低下させます。
Wheel Colliderを追加すると、車が道路と衝突する場所を制御できます。

開始()-インストール


これは、車に必要な初期化を行う場所です。 Start()関数は、 Update関数の前に、スクリプトの最初で1回だけ実行されます。 したがって、 Start()は 、コードのコンポーネントに必要な初期値を設定するためによく使用されます。

SetupWheelColliders()


車には4つの車輪が取り付けられており、 それらインスペクターFrontWheelsおよびRearWheels配列に配置します。 この機能では、実際のコライダーを作成し、車輪と表面および車との相互作用の可能性を作成します。 SetupWheelFrictionCurve()関数から始めます

SetupWheelFrictionCurve()


SetupWheelFrictionCurve()で 、新しいWheelFrictionCurveを作成し、車に適切と考える値を割り当てます。 WheelFrictionCurveWheelColliderを使用して、ホイールタイヤの摩擦特性を記述します。 WheelCollidersを使用して構築されたUnityで車を作成するプロセスをさらに詳しく知りたい場合は、ドキュメントを読んでください。

SetupWheel()


曲線を調整し後、 SetupWheelColliders()スクリプトに戻り、 コライダーホイールオブジェクトを作成する準備ができました。 これは、各ホイールに対してSetupWheel()関数を呼び出すことで実行されます。 この関数を見ると、 Transformbooleanの 2つのパラメーターがあり、 Wheelオブジェクトを返すことがわかります。 これは、車輪の位置を変更したり、車輪が車の前を指しているかどうかを示すために必要です。 次に、関数はWheelオブジェクトを作成して返します。これは、スクリプトの残りの部分のすべての車輪を含むwheels配列に入れます。

for (var t : Transform in frontWheels) { wheels[wheelCount] = SetupWheel(t, true); wheelCount++; } 

このループでは、新しいゲームオブジェクトを作成し、 SetupWheel()関数を呼び出し、最初の引数としてオブジェクト座標を渡し、 TRUEの 場合は2番目のパラメーターとしてTRUEまたはFALSEを指定します。TRUEの場合、作成されたホイールはフロント、 FALSEの場合はバックになります。 次に、このゲームオブジェクトにWheelColliderコンポーネントを追加します。 車のセットアップ時に説明したサスペンション変数(サスペンションレンジ、サスペンションスプリング、ダンパー)(サスペンションレンジ、スプリング、ダンパー)からWheelColliderプロパティを設定します。

必須のプロパティ:既にコライダーを作成し、 WheelFrictionCurveWheelFrictionCurve()関数で作成され、ホイールのグラフィックス(車を作成したときにインスペクターでDiscBrakeオブジェクトをドラッグしました)、タイヤのグラフィックス( DiscBrakeの子)です。

タイヤのサイズに応じて、ホイールの半径を自動的に設定します。

 wheel.collider.radius = wheel.tireGraphic.renderer.bounds.size.y / 2; 

最後に、前輪か後輪かにかかわらず、作成したばかりのホイールをチェックし、 TRUEまたはFALSEの値を確認します。 コードの後半では、少なくとも1つの前輪と1つの後輪で車が地面に触れていることを確認する必要があります。

さらに、前輪の小さなレセプションを作成し、車体とホイールの間に追加のゲームオブジェクトを作成します。 これは、 後部で回転するときにホイールを回転させるために使用するSteer Column(フロントピラー)です。最後に、 Wheel配列に戻るホイールを作成し、すべてのホイールを処理したら、 Start()関数に戻ります。

SetupCenterOfMass()


これは、次に検討する機能です。 これは、 リジッドボディ重心を前に作成したCenterOfMassに設定する非常に小さな関数です。 重心が設定されいない場合、 RigidbodyUnityを自動的に計算するデフォルトの重心を使用します。 次に、小さな便利な関数を使用して、インスペクターに入力された最大速度を変換します。

 topSpeed = Convert_Miles_Per_Hour_To_Meters_Per_Second(topSpeed); 

この関数は、 TopSpeed変数に数値0.44704を乗算するだけで、1秒あたりのメートルに変換します。 これが設定であるため、マイル/時でインスペクターに希望の速度を入力できます。 物理学を計算するとき、m / sを使用します。 また、逆計算を行う小さな関数もあります。これは、車の速度をマイル/時間で表示する場合に非常に便利です。

SetupGears()


この機能では、各ギアに最大速度を割り当て、各ギアで所定の速度まで車を加速するのに必要な電力を計算することにより、ギアが自動的に計算されます。 電力は、任意の変数に供給される摩擦と抵抗の値を使用して計算されます。これは、Z軸に沿った主な計算を意味し、摩擦の計算はUpdate()関数で発生します。 車が高速に加速するように、係数にこのパワーの値が乗算されます。

SetupSkidmarks()


この関数は、シーン内でSkidmarkゲームオブジェクトを見つけ、 ParticleEmitterを使用して煙作成するためのリンクを保存ます。 skidmarksのコードはこのガイドではカバーされていませんが、スクリプトを開いて、必要に応じて調査することを妨げるものではありません。 Start()の最後で、 dragMultiplier配列のX値を変数に割り当てます。

 initialDragMultiplierX = dragMultiplier.x; 

ハンドブレーキを使用するときにX変数dragMultiplierを変更し、 ハンドブレーキを使用しないときに再び元の値に戻す必要があるため、保存されます。

初期値を設定するには、 Start()関数を使用します。 これらの値を定期的に変更するには、 Update()関数を使用します

更新()


MonoBehaviourが有効になっている場合、 Update()はゲームのフレームごとに呼び出されます。
更新()は、ゲームプレイを実装するために最も一般的に使用される機能です。

GetInput()


各フレームで最初に行うことは、 GetInput()関数を呼び出すことによるキーボードからの異なるアクションです。 最初の2行は、 垂直(垂直)および水平(水平)軸から読み取られ、 スロットルおよびステア変数に格納されます

 throttle = Input.GetAxis(“Vertical”); steer = Input.GetAxis(“Horizontal”); 

Unity Input Manager(編集->プロジェクト設定->入力)で 垂直と水平軸を設定できます。 デフォルトでは、 垂直軸はキー「W」、「上矢印」で前方に移動し、キー「S」、「下矢印」で後方に移動します。ここで使用する値はスロットル変数に保存されます。 水平軸は、左に曲がる「A」および「左矢印」キー、および右に曲がる「D」および「右矢印」キーとして設定されます。

CheckHandbrake()


ドライブするGetInputを学習した後、 CheckHandbrake()関数を呼び出します。 これは、 スペースキーが押されているかどうかをチェックし、それに応じて特定のロジックを適用する特定の機能です。

最初にSpace(スペース)を押したときに、 handbrake変数をtrueに設定します 。これにより、 handbrakeメカニズムが開始され、 dragMultiplier.xの値が変更されます(実際のハンドブレーキに似た道路にブレーキ振動を作成します)。

Spaceが押されていない場合、キーが押されるまでコードは異なる方法で実行されます。 これは、ブロック内でhandbrake変数をfalseに設定しているため、ユーザーが最初にSpace(スペース)を解放したときにのみハンドブレーキコードが機能しないことを意味します。 StopHandbraking()関数がアクティブになります:

 StartCoroutine(StopHandbraking(Mathf.Min(5, Time.time - handbrakeTime))); 


StopHandbraking()


StopHandbraking()は、 dragMultiplier.xを元の状態に戻すのにかかる秒数を決定する入力変数を受け入れます。 この値は、開始したハンドブレーキタイマーに対して少なくとも5でなければなりません。 次に、関数は指定された秒数をカウントダウンし、その後dragMultiplier.x変数をデフォルト値に設定します。これにより、車の動きが再び通常になります。

Check_If_Car_Is_Flipped()


Update()関数に戻って、 Check_If_Car_Is_Flipped()関数を調べて、マシンが逆さまになっているかどうかを確認します。 この関数内で、反転したマシンをチェックします。 これは、車が転倒したり、極端な曲がり角で曲がったり、事故や何らかのトリックを行う場合には絶対に当てはまりますが、車の転倒の可能性を排除したいのです。 そのため、自動車が特定の角度で回転したかどうかを確認します。この角度では、自動車は移動していません。その場合、最後のフレームの瞬間からresetTimer変数を追加します。 この値が最終的にresetTimeに設定した値(デフォルトでは5秒)を超えた場合、 FlipCar()関数を呼び出します。 車があなたが乗ることができる角度にある場合、タイマーをゼロに戻します。

FlipCar()


FlipCar()では 、車を車輪に戻し、速度を0に設定して、この場所から再び移動できるようにします。

UpdateWheelGraphics()


これは、 Update()から呼び出される最も長く複雑な関数です。 幸いなことに、 タイヤトラックの配置のみを扱うこの大きなセクションがあります 。 ホイールに関する重要な役割は、この機能で位置と回転角度を更新することによって行われます。

車輪が地面に触れるかどうかを確認して、各車輪を起動します。 地面に関する場合は、 wheelGraphic (ホイールのグラフィック)をあるべき位置に設定します。これは、ホイールの高さと半径に依存します。 これにより、ホイールの中心が車両のシャーシに対して正しい位置に移動します。

 w.wheelGraphic.localPosition = wheel.transform.up * (wheelRadius + wheel.transform.InverseTransformPoint(wh.point).y); 

車輪を取り付けた後、地面との接触点でRigidBodyの速度を取得して、それをローカルスペースに転送し、その座標を施設に保存します。

 w.wheelVelo = rigidbody.GetPointVelocity(wh.point); w.groundSpeed = w.wheelGraphic.InverseTransformDirection(w.wheelVelo); 

ホイールが現在地面に触れていない場合、その座標、サスペンションの範囲、および 「親のホイール」 サスペンション自体に基づいてホイールの位置を設定します

UpdateGear()


Update()関数で最後に呼び出される関数はUpdateGear()です 。これは、 SetupGears()で設定された値と現在の速度に基づいて、車の現在の「伝達」を計算します。 マニュアルの最後のセクションでは、メインサイクルの残りの部分、つまりFixedUpdate()関数内で発生する物理計算について検討する必要があります。

FixedUpdate()-すべての物理学


物理学を扱う場合、結果が良好になるように計算とアクションを厳密に制御することが重要です。 FixedUpdate()は 、この目的のために作成されます。 これにより、コードは一定の時間間隔で実行されます。 FixedUpdate()関数を呼び出す頻度:「フレームレートが低い場合、フレーム内で数回呼び出すことができます。 または、フレームレートが高い場合は、数フレーム後に呼び出すことができます。 すべての物理計算と更新は、 FixedUpdate()の直前に呼び出されます。 FixedUpdate()内で実行される多くの機能があり、それらはすべて、車の力の計算と適用に関連しています。

UpdateDrag()


これは、速度が上がると抵抗がさらに増えることを意味します。 抵抗の計算における速度の二乗は、物理学で使用されている現在の抵抗式に基づいています。

relativeDrag(相対抵抗)とスケーラブルなdragMultiplier(抵抗乗数)については既に検討しましたが、プロファイル内の車の外観が正面、側面、上面から大きく異なっていることを考慮しました。

車の進行速度に基づいて、 ハンドブレーキに横方向および正面方向の抵抗値に余分な力を加えた場合。 車の速度と正面方向の間のスカラー積を使用して、追加の抵抗を計算する方法に注目してください。 この方程式は、ドリフトせずに(急ブレーキ)ドリフトせずに前進するときに、車両の前に抵抗を追加し、ドリフトおよびターンでのブレーキを遅くします。 X抵抗の値についても、同じことです。車が横にスライドしている場合。 その後、抵抗値Xを徐々に増やして、車を常に路上で滑らせるのではなく、減速させます。

ハンドブレーキを使用しない場合は、 Xの値のみを更新します。

 drag.x *= topSpeed / relativeVelocity.magnitude; 

これは、車に快適に乗るために行われます。横方向の抵抗を増やします。これにより、車が横滑りを完了するまで、横滑りの際に車の速度が徐々に遅くなります。

関数の最後で、 RigidBodyに力を適用します。

 rigidbody.AddForce(transform.TransformDirection(drag) * rigidbody.mass * Time.deltaTime); 

抵抗力は車の速度と反対であり、それをRigidBodyに適用します。その結果、車は減速します。

UpdateFriction()


この機能は、車の車輪とルートの表面との間に生じる摩擦を監視します。 最初に設定したWheelFrictionCurve関数を使用しているため、非常に簡単です。 ホイールの摩擦は、関数に渡したタイヤスリップの測定値に基づいて、関数の「出力」に力を与えます。 この力は2つの方向に分けられます:正面摩擦(加速とブレーキングに責任があります)および側面摩擦(地面での車の適切なメンテナンスに責任があります)。 以前は、ホイールの摩擦の値を割り当てていましたが、ホイールとサーフェスの間の摩擦を更新する必要があります。

 w.collider.sidewaysFriction = wfc; w.collider.forwardFriction = wfc; 

1つのアクションを実行します-車の現在の速度と車の方向に基づいて車の摩擦の値を変更します(通常の運転-ForwardFriction 、および車の横滑りに基づいて- " sideways" sidewaysfriction )。

CalculateEnginePower()


後でRigidBodyに力を加えるために使用するエンジン出力の計算比較的簡単ですが、いくつかの「癖」があります。

スロットルを行わない場合、エンジンの出力を下げるだけで、車の速度が低下します。
•車が現在動いているのと同じ方向にスロットルをかけた場合( HaveSameSign()関数を使用してこれを確認します)、エンジンの出力に追加する値を計算します。 少し奇妙に見えるかもしれません:現在のエンジン出力を最大エンジン出力で割った結果である力率を計算し(0から1の間の結果が得られます)、2倍します。 結果は、0(静止しているか、非常にゆっくりと食べる)と2(最大出力で食べる)の間になります。 次に、ヘルパー関数EvaluateNormPower()を呼び出します。 この関数は、送信された値を調べて、電力ノルムが0〜1の場合、1〜0の数値を返します。電力ノルムが1〜2の場合、関数は0〜1の値を返します。 エンジンに強度を追加する式で使用される数値:

 currentEnginePower += Time.deltaTime * 200 * EvaluateNormPower(normPower); 

最終結果は、「ガス」ボタンを押すとさらにパワーが追加され、車は最初からゆっくりと運転し、徐々に加速することです。 最終的に、車が最大速度に達すると、追加するために追加の力は使用されなくなります
エンジン出力。

•逆方向のスロットルを使用する場合、これはブレーキ操作と同等です。 この場合、しばらくの間エンジン出力を差し引きます。

最後に、計算式の値が突然変更される可能性を避けるために、現在のギアと前のギアの間でエンジン出力が計算されます。

CalculateState()


これは、どの車の車輪が地面にあるのかを知る必要があるので、これから見る小さな機能です。 彼女はこのチェックを非常に簡単にします
canDriveおよびcanSteer変数をデフォルトでFalseに設定します。
•次に、Wheels配列の各ホイールをチェックして、地面に触れるホイールと触れないホイールをチェックします。
 if(w.collider.isGrounded) 

車輪が地面にある場合、車輪の種類を確認します。 前輪の場合、 canDriveは Trueに設定されます 。 これが後輪の場合、 steerWheelは Trueに設定されます 。 少なくとも1つの車輪(後輪)が地面に触れると、この機能が機能し、車を制御できます。 少なくとも1つの車輪(前輪)が地面に触れると、方向転換できます。

RigidBody車の計算に実際に関係する最後の2つの関数を検討する必要があります。 ここでは、作業のロジックと最終的に車の動きを作成する計算式を理解できるように、ここでさらに詳しく見ていきます。

ApplyThrottle()


CalculateState()関数がcanDrive変数をTrueに設定すると、この関数は機能します (これは、道路上に少なくとも1つの駆動輪があることを意味します)。 制御できる場合は、 スロットル変数(キーボードからのキーストローク)と車両速度が存在するrelativeVelocity.z変数を比較することから始めます。 HaveSameSign()関数で定義されたこれらの値に同じ符号がある場合、これは車が進む方向と同じ方向にスロットルすることを意味します。この場合、スロットル力をRigidBodyに追加します

 throttleForce = Mathf.Sign(throttle) * currentEnginePower * rigidbody.mass; 

スロットル値が負の場合(ユーザーがブレーキボタンを押した場合)、符号は-1になり、マシンに追加する負のthrottleForce(スロットル力)を計算します。また、スロットル力には負の速度があることもわかります。 そのため、より速くスロットルバックします。 ユーザーがガスボタンを押したときの逆の効果。 次に、すでに前進している車に「正の」スロットルフォースを追加します。

relativeVelocity.zとスロットルの符号が異なる場合、これは車が現在走行している方向とは反対方向にスロットル力を加えることを意味するはずです。 言い換えれば、車は減速するか減速します。 これを行うには、車の質量とエンジンの最初のギアの出力に基づいてBrakeforce変数を設定します。

 brakeForce = Mathf.Sign(throttle) * engineForceValues[0] * rigidbody.mass; 

この場合もスロットルは速度の反対の符号を持っていることがわかっているため、 スロットルを使用します。その結果、車を駆動する力と反対の力を計算します。

車が加速または減速するために必要なものの決定が終了したら、計算された力を剛体の移動方向に適用します。

 rigidbody.AddForce(transform.forward * Time.deltaTime * (throttleForce + brakeForce)); 

ApplySteering()


ストレートランで世界記録を樹立しようとするドラッグレースゲームを作成していない場合、ステアリングコントロールはスロットルと同じくらい重要なので、この機能を調べてみましょう。 駆動輪が地面に触れない限り、スロットルをかけることはありません。 ステアリングホイールが地面に触れない限り車を運転できないこの機能についても同様です。

関数の最初で、入力データに基づいてturnRadiusという変数の値を計算します。 方程式は、どちらかの側に曲がるとturnRadiusの値を増やします。 EvaluateSpeedToTurn()関数を呼び出して、 minMaxTurnの値を計算します。

EvaluateSpeedToTurn()


この関数は、車の速度に応じてターン値を返します。これについては、マニュアルの第2章で詳しく説明します。 車が速くなると、この値はminimumTurnに近くなり、高速移動中に車を回すのが難しくなります。 ApplySteering()関数に戻りましょう。 ここで、 turnSpeedは車内のturnRadiusの計算を直接参照します。 回転円が大きいため、半径が大きいほど、回転角度は小さくなります。

次の式に従って車を回します。

 transform.RotateAround( transform.position + transform.right * turnRadius * steer, transform.up, turnSpeed * Mathf.Rad2Deg * Time.deltaTime * steer ); 

RotateAround()関数は、指定されたポイントで変換された軸を中心に回転し、回転の合計である角度を取ります。

•車をまったく回転させない場合、ピボットポイントは車のちょうど中央にあります。 , , . , Steer , , , . TurnRadius , . TurnRadius transform.right , , :

画像

Y (up) , , X-車を画像に示されている線に向けます。
•回転角度はに基づいて計算されturnSpeedを掛けステア回転させるには、左/右

次に内側から検討します。

 if(initialDragMultiplierX > dragMultiplier.x) 

ハンドブレーキ機能で思い出したように、少なくとも1つの前輪が地面に触れているかどうかを確認しました。

車が静止していない場合、RigidBodyのangleVelocity.yの値を見て、車が現在回転しているかどうかを確認ます。この値がゼロまたは非常に小さい場合、回転しないか、ごくわずかな角度しか回転せず、回転が行われる方向にランダムな値を適用します。これはハンドブレーキを使用中の車の不安定さをシミュレートします。

値がそれほど低くない場合は、代わりにangleVelocity.yの実際の値を回転方向に適用します。左に曲がるとき、値は-1になり、右に曲がるとき、値は1になります。

ハンドブレーキを使用すると、車は向きを変えますが、ブレーキには別のサポートポイントが使用されます。

 frontWheels[0].localPosition + frontWheels[1].localPosition) * 0.5 

このポイントは2つの前輪の間にあり、車が回転すると、車の後部が車の回転方向に移動し、前部がその位置を保持します- ハンドブレーキを使用すると車は高速で滑ることができます。

これで円が閉じられ、関数Update()LateUpdate()連携して機能しますその変数で遊んでコードを調べて、車を作ることについて学んで楽しんだことを願っています。

実際の物理モデル


(Project view) ~ AlternatePhysicsModel . Prefabs Unity . (wheel colliders) Unity , (wheel collider) Physics.Raycast . Pacejka « /Magic Formula» — , .

ほとんどの場合、物理モデルの内部動作について知る必要はありません。作成済みのプレハブの設定を試すだけですスクリプトを開くと、すべてのパラメーターがコメントで説明されていることがわかります。設定を少し変更して運転してみてください。

含まれているプレハブ


Prefabs (skidmarks) Prefabs . , (Skidmarks Prefab) (, Prefabs skidmarks ). .

, «» ( ).

, TractionHelper ジョイスティックの助けを借りて、車をより管理しやすくするように設計されています。

含まれるスクリプト


AerodynamicResistance.cs:このスクリプトは、車の空力摩擦を計算するために各車に追加する必要があります。

AntiRollBar.cs:必要に応じて追加し、アンチロールバーをシミュレートして処理を改善します。

CarController.cs:車のコントロールを処理するためのスクリプト。このスクリプトは各車に必要です。車の制御を変更したり、AIを実装したい場合は、このスクリプトを編集できます。また、重心や慣性など、車体のいくつかの特性も確立します。

Drivetrain.cs:車のエンジンとトランスミッション。このスクリプトには、ギアボックスとエンジンが含まれています。車に必要なスクリプトの1つ。

Skidmarks.cs:グローバルブレーキトラックマネージャー(スキッドマーク)このクラスがすべての車のスキッドマークを視覚化および管理するために使用するシーンにスキッドマークプレハブ追加します。SoundController.cs:車の音やその他の音を再生する単純なクラス。このスクリプトを車に追加する必要があります。TractionHelper.cs:必要に応じて、このスクリプトを車に追加してより安定させます。このスクリプトは、柔軟な車両制御のセットアップに役立つように設計されています。Wheel.cs:このスクリプトは、タイヤモデルとホイールサスペンションを模倣し、Unityの組み込みコンポーネントの代わりとして機能します





ホイールコライダー。

Wing.cs:車の空力のダウンフォースをシミュレートする場合は、1つまたは複数のスクリプトを追加します。

翻訳者による分析と結論


私は2つの運転方法を研究しました。最初の方法は運転が簡単で、スクリプトの概念がわかりましたが、欠点があります:
1)上り坂になり、重力でも山を70度の角度で下りません。
2)前進するとき、急に後退してキーを放すと、車は急に前進します。
3)車はでこぼこの道を「飛び」、現実的に着陸しません。
4)Rigidbodyに手動でDragとAngular Dragを含めても(実際には、物理​​モデルの相互作用中の抵抗は依然として急な山を登ります)。
2番目の方法は実際にはより現実的であり、これらの欠点がありません。 (〜AlternatePhysicsModel)。
実際のビデオは次のとおりです。Lambordgine-方法2、例の方法1の標準マシン



: , « » 1. , — 2.

Source: https://habr.com/ru/post/J248995/


All Articles