ドナドナされるプログラマのメモ

Windows用アプリのプログラミングメモ

鉄道車両の車輪をカプセルColliderで模擬してみる(手探り編)

踏面の形状をCapsuleCollidorで模擬したけど、これダメだ。間違いなく、ポイントで乗り上げる。

仕方ないので、CapsuleCollidorは使うけど円筒の側面だけ活用する方向で。レールの中心に沿う機能、どうしよう。フランジだけじゃあ無理だよなあ。

新南陽ヤードの構造

L4カーが稼働していた新南陽ヤードの当時の構造はどうなっていたんだろう?国土地理院の航空写真を見てみたけど、撮影時期が1974~1978と幅があり、掲載されている写真が稼働を開始した1978年以後なのかがわからなかった。まあでも、こんなかんじらしい。

f:id:donadonasan:20190806210306p:plain

南陽ヤード(1974~1978のどこか)

当時の地図はないのかな。あれば線路が書かれていそうだけど。

鉄道車両の車輪をカプセルColliderで模擬してみる(準備編)

鉄道車両の車輪とレールとの当たり判定をCapsule Colliderで模擬することにしたわけだが、このためにはレールとColliderが接触する部分の傾きを本物とだいたい同じにする必要がある。本物の踏面は1:20の傾斜になっており、また車輪一対の中心から560mmの場所で測った車輪の直径が860mmとなっている。

f:id:donadonasan:20190804174906p:plain

国鉄の車輪寸法 (鉄道辞典 pp.1009より)

以上から、作るべきCapsule Colliderの半径rと、球と球の距離dが求まる。球と車輪の直径を量る場所とのなす角をθ°とすると、

tanθ = 1/20 より θ = 2.86°

r cosθ = 860/2 より r = 430.5

d = 560 - r sinθ より d = 538.5

なんか、ほとんど円筒だ。うまくいくのかなあ。

鉄道車両の車輪寸法を調査した

レールと車輪の当たり判定について、車輪側をカプセルで模擬してみる。そのためには車輪の寸法が必要だ。以下に、調査結果をまとめる。

車輪のモデル

Unityでは、物理シミュレーションできるオブジェクトの当たり判定メッシュとして凸なものしか使えないようだ。なので、レールとの当たり判定を車体全体でやるのは無理がある。そもそも、車輪ですら踏面とフランジのせいで凹み部あるし。

じゃあ、どうすればうまく当たり判定させつつ物理シミュレーションできるんだろう?踏面とフランジを別部品で作ってそれぞれに当たり判定をつけ、両者を結合させればいいのだろうか?まずはその方向で行くことにしよう。

フランジと踏面の結合方法

ある2つの物体をくっつけるには、親子関係を使う方法と、Fixed Jointを使う方法があるようだ。今回の例だと、

  • 親子関係:車輪というGame Objectの中に、踏面とフランジ、車軸をぶち込む。それぞれの関係は固定されており、ゲーム中に変化しない。
  • Fixed Joint:フランジにJointコンポーネントを追加し、踏面に対するFixed Jointを作成する。一定以上の力が加わったときに接続が切れたりしてほしいときなどに使う。

となるのかな。ゲーム中に接続状態を変える必要がないので、親子関係で作ればよさそう。

踏面のCollisionモデルをどうするか

鉄道用車輪の踏面は、自動車のタイヤ(円筒形)とは異なり円錐形である。しかし、Unityには円錐用のCollisionモデルは無い。では、これとレールとの衝突判定はどのようにすればよいだろうか?

例えば、踏面のMeshを作り、これとレールのMeshを衝突判定させる手がある。しかし、踏面のMeshはMeshゆえに表面の曲線を多数の直線で近似しており、表面がでこぼこしてしまう。そのため、これが回転するとガタガタ上下動すると思われる。これは良くないので、他に手段がない場合にのみ使うことにする。

他には、Wheel Colliderも使えるかもしれない。これは車輪を円盤に見立てて、舵角や回転力等を与えると回転量や車輪の位置を計算してくれる。サスペンションの効果や静・動摩擦力まで考慮してくれるスグレモノだ。しかし、である。これは自動車のタイヤを円盤に近似しており、踏面には直接適用できない。レールと踏面の相対位置から円盤の半径を計算して適宜変更するようにすれば行けるのかもしれないが。惜しいので、この方式は次善の策とする。

あとは、円錐を、十分に半径の大きな球の表面の一部とみなす手もある。この場合の問題は、おそらく巨大となるCollision球同士の当たり判定を避けられるか?という点と、踏面の半径と球の半径が整合しない場合、回転量の計算などをどうするのか?という点である。これらの問題は、踏面の半径とCollision球の半径を等しくすれば解決できるので、まずは踏面の半径とCollision球の半径を等しくしてもよいか確認するところから始めれば良さそう。

Unityでのメッシュオブジェクト当たり判定

レールの上に車両を置けるか試すため、手元にあったレールと貨車をおいてみた。当たり判定がちゃんと発生するようになるまで手間取ったけど、無事乗った。

ワム80000の方は、MMD用の.pdxファイルをBlenderにインポート後、テクスチャごとエクスポートするために.fbxで出力しUnityに取り込んだ。その後、モデルに対し2箇所設定変更してSceneへぶちこみ。

f:id:donadonasan:20190728155732p:plain

取り込み設定

Sceneへぶちこんだオブジェクトを見るとMeshがいるので、そこにMesh_Colliderを追加していくつか設定。

f:id:donadonasan:20190728160039p:plain

ワム80000 Mesh_Collider設定

次に、レールをインポート。こちらはSketchUp!から直接取り込み。この場合、最初から適切な設定がされているので特に作業はしなかった。

そして、当たり判定ができていることを確認するため、わざと高さ10cmから落としてみる。

f:id:donadonasan:20190728162814g:plain

当たり判定のテスト

だいたいオッケーぽい?

ただ、貨車側の当たり判定メッシュを確認してみたら、どうも凹みがないように全体が凸となるメッシュとなっていた。これでは、上に凸なレールを走った際に車輪と車輪の間にあるメッシュが引っかかってしまう。当たり判定は車輪に限定したほうがいいのかな。あと、下に凸なレールでも同様の問題が出てしまうけど、どうしよう。ちょっと悩ましい。

f:id:donadonasan:20190728155149p:plain

ワム80000の当たり判定メッシュ

 追記:RigidBodyを持っていない(物理シミュレーションがいらない)やつなら、凸ではないメッシュが使えるぽい。レールは物理シミュレーションが不要なので、問題なさそう。