PR

【Unity】フライトシミュレーターを作る:新機体の実装

Unityを使って作成した鳥人間コンテストの滑空機部門を想定したフライトシミュレーターに新機体を実装するやり方についての開発者用の備忘録

実際に作成したフライトシミュレーターはこれ

keywords: Unity,物理演算,フライトシミュレーター,人力飛行機,微小擾乱理論

スポンサーリンク

はじめに

Unityを使って作成した鳥人間コンテストの滑空機部門を想定したフライトシミュレーターに新機体を実装するやり方について説明する

Unityのバージョンは2020.3.8f1

Unityについては多くの入門サイトがあったが,今回特に参考にしたのはこちら

Unityの全般的な知識は上のサイトで,物理演算の基本については下のサイトを参考にした

Unity入門【初心者為の使い方講座】【実際にゲームを作って解説】 _ ゲームの作り方!
Unity カテゴリーの記事一覧 - エフアンダーバー

↓鳥人間コンテストのフライトシミュレーターの先駆者様

みえ日記
メインページは外部リンクから

↓今回作成したプログラム

mtkbirdman.com/BirdmanRallySim at master · mtkbirdman/mtkbirdman.com
mtk_birdman's blog @mtk_birdman. Contribute to mtkbirdman/mtkbirdman.com development by creating an account on GitHub.

↓その他の解説記事

それではいってみよう

新機体実装の手順

BRSimulatorに新しい機体を実装するときは以下の手順で行う

  1. 3Dモデルを作って.objで出力する
  2. 機体諸元を計算する
  3. objファイルをUnityにインポートする
  4. インポートしたモデルをシーンに追加する
  5. オブジェクトの親子関係を整理してMesh Colliderを追加する
  6. 機体のオブジェクトの設定を行う
  7. 垂直尾翼と水平尾翼のオブジェクトの設定を行う
  8. 機体オブジェクトにカメラを追加する
  9. モデル選択画面のサムネ画像を撮影する
  10. モデル選択ボタンを追加する
  11. 機体諸元を入力する

それでは1つずつ説明していく

3Dモデルを作って.objで出力する

以下の条件を満たす3Dモデルを製作する

  1. 機体後方にx軸,機体上向きにy軸,左翼側にz軸
  2. エレベーター,ラダー,それ以外のすべて(本体),の3つのパーツ構成
  3. 主翼翼根の桁中心にモデルの原点
  4. 上の原点から計測したエレベーター,ラダーの回転軸の位置
  5. 上の原点から計測した重心位置および重心位置まわりの慣性モーメント

1.の条件は機体をきちんとした向きでゲーム内に配置するための必須条件である

座標系や回転についての詳細は下の記事を参照

2.,3.,4.の条件は舵面を動かすために必要な項目で,5.の条件は物理演算に必要になる

これらの条件を満たした3Dモデルを.obj形式で出力する

ボディを右クリック>メッシュで保存>形式:OBJ>リファインメント:高>OK

ちなみに.objファイルは色のデータを保持しないので,モデルの色は特に気にしなくていい

Wavefront .objファイル - Wikipedia

できればフライト中の翼がたわんだ状態のモデルのほうが現実味があって良い

機体諸元を計算する

機体の物理演算を行うために,以下の点に注意して機体諸元を計算する

  • 諸元を計算するときに地面効果は考慮しない
  • 地面効果は物理演算内で考慮する(\(C_{GE_{min}} = 0.2 \sim 0.4\))
  • カウルや胴体の有害抗力係数はだいたい\((C_{D_{p}})_{body}=0.200\)として計算する

必要な諸元の一覧は以下のとおり

変数名説明単位
Rigidbody.massfloat全備重量kg
Rigidbody.centerOfMassVector3重心位置m
Rigidbody.inertiaTensorVector3重心まわりの主慣性モーメントkg m^2
Rigidbody.inertiaTensorRotationQuaternion慣性主軸への回転を表すクォータニオン-
Airspeed0float設計速度m/s
alpha0float設計迎角deg
CDp0float全機有害抗力係数の最小値-
Cmw0float主翼空力中心回りの主翼ピッチングモーメント係数-
CLMAXfloat主翼および尾翼の最大揚力係数(共通)-
Swfloat主翼翼面積m^2
bwfloat主翼翼幅m
cMACfloat主翼平均空力翼弦長m
awfloat主翼三次元揚力傾斜1/deg
hwfloat主翼空力中心と全機重心の距離(cMACで無次元化)-
ewfloat主翼翼効率(楕円翼を1としたときの誘導抗力の大きさ)-
Downwashbool吹きおろしの計算を行うかどうか(通常配置: true,T字尾翼: false)-
Stfloat水平尾翼面積m^2
atfloat水平尾翼三次元揚力傾斜1/deg
ltfloat水平尾翼空力中心と全機重心の距離m
deMAXfloatエレベーターの最大舵角deg
taufloat舵面の効きを表す係数(白本:p.83)-
drMAXfloatラダーの最大舵角deg
CGEMINfloat地面効果係数の最小値(0<CGEMIN<1)-
Cyb,Clb,Cnbfloat横滑りに関する安定微係数1/deg
Cyp, Clp, Cnpfloatロール角速度に関する安定微係数1/rad
Cyr,Clr,Cnrfloatヨー角速度に関する安定微係数1/rad
Cydr,Cldr,Cndrfloatラダー舵角に関する安定微係数1/deg

実際にシミュレーターに入力されている値はこれ

void InputSpecifications()
{
    if(MyGameManeger.instance.PlaneName == "QX-18"){
        // Plane
        PlaneRigidbody.mass = 93.875f; // [kg]
        PlaneRigidbody.centerOfMass = new Vector3(0f,0.221f,0f); // [m]
        PlaneRigidbody.inertiaTensor = new Vector3(876f,947f,76f);
        PlaneRigidbody.inertiaTensorRotation = Quaternion.AngleAxis(-4.833f, Vector3.forward);
        // Specification At Cruise without Ground Effect
        Airspeed0 = 9.700f; // Magnitude of ground speed [m/s]
        alpha0 = 1.682f; // Angle of attack [deg]
        CDp0 = 0.018f; // Parasitic drag [-]
        Cmw0 = -0.164f; // Pitching momentum [-]
        CLMAX = 1.700f;
        // Wing
        Sw = 18.042f; // Wing area of wing [m^2]
        bw = 25.133f; // Wing span [m]
        cMAC = 0.757f; // Mean aerodynamic chord [m]
        aw = 0.108f; // Wing Lift Slope [1/deg]
        hw = (0.323f-0.250f); // Length between Wing a.c. and c.g.
        ew = 0.949f; // Wing efficiency
        AR = (bw*bw)/Sw; // Aspect Ratio
        // Tail
        Downwash = true; // Conventional Tail: True, T-Tail: False
        St = 1.375f; // Wing area of tail
        at = 0.076f; // Tail Lift Slope [1/deg]
        lt = 4.200f; // Length between Tail a.c. and c.g.
        deMAX = 10.000f; // Maximum elevator angle
        tau = 1.000f; // Control surface angle of attack effectiveness [-]
        VH = (St*lt)/(Sw*cMAC); // Tail Volume
        // Fin
        drMAX = 10.000f; // Maximum rudder angle            
        // Ground Effect
        CGEMIN = 0.215f; // Minimum Ground Effect Coefficient [-]
        // Stability derivatives
        Cyb = -0.002410f; // [1/deg]
        Cyp = -0.228437f; // [1/rad]
        Cyr = 0.090542f; // [1/rad]
        Cydr = 0.001908f; // [1/deg]
        Clb = -0.002002f; // [1/deg]
        Clp = -0.877559f; // [1/rad]
        Clr = 0.237651f; // [1/rad]
        Cldr = 0.000052f; // [1/deg]
        Cnb = -0.000059f; // [1/deg]
        Cnp = -0.142441f; // [1/rad]
        Cnr = -0.000491f; // [1/rad]
        Cndr = -0.000262f; // [1/deg]
    }else if(MyGameManeger.instance.PlaneName == "QX-19"){
        // Plane
        PlaneRigidbody.mass = 96.631f;
        PlaneRigidbody.centerOfMass = new Vector3(0f,0.294f,0f);
        PlaneRigidbody.inertiaTensor = new Vector3(991f,1032f,60f);
        PlaneRigidbody.inertiaTensorRotation = Quaternion.AngleAxis(-9.134f, Vector3.forward);
        // Specification At Cruise without Ground Effect
        Airspeed0 = 8.800f; // Magnitude of ground speed [m/s]
        alpha0 = 1.554f; // Angle of attack [deg]
        CDp0 = 0.019f; // Parasitic drag [-]
        Cmw0 = -0.170f; // Pitching momentum [-]
        CLMAX = 1.700f;
        // Wing
        Sw = 18.275f; // Wing area of wing [m^2]
        bw = 26.418f; // Wing span [m]
        cMAC = 0.736f; // Mean aerodynamic chord [m]
        aw = 0.105f; // Wing Lift Slope [1/deg]
        hw = (0.323f-0.250f); // Length between Wing a.c. and c.g.
        ew = 1.010f; // Wing efficiency
        AR = (bw*bw)/Sw; // Aspect Ratio
        // Tail
        Downwash = true; // Conventional Tail: True, T-Tail: False
        St = 1.548f; // Wing area of tail
        at = 0.082f; // Tail Lift Slope [1/deg]
        lt = 3.200f; // Length between Tail a.c. and c.g.
        deMAX = 10.000f; // Maximum elevator angle
        tau = 1.000f; // Control surface angle of attack effectiveness [-]
        VH = (St*lt)/(Sw*cMAC); // Tail Volume
        // Fin
        drMAX = 10.000f; // Maximum rudder angle            
        // Ground Effect
        CGEMIN = 0.361f; // Minimum Ground Effect Coefficient [-]
        // Stability derivatives
        Cyb = -0.005300f; // [1/deg]
        Cyp = -0.567798f; // [1/rad]
        Cyr = 0.225280f; // [1/rad]
        Cydr = 0.001721f; // [1/deg]
        Clb = -0.005118f; // [1/deg]
        Clp = -0.827488f; // [1/rad]
        Clr = 0.296796f; // [1/rad]
        Cldr = 0.000050f; // [1/deg]
        Cnb = -0.000808f; // [1/deg]
        Cnp = -0.165533f; // [1/rad]
        Cnr = 0.001675f; // [1/rad]
        Cndr = -0.000208f; // [1/deg]
    }else if(MyGameManeger.instance.PlaneName == "QX-20"){
        // Plane
        PlaneRigidbody.mass = 98.797f;
        PlaneRigidbody.centerOfMass = new Vector3(0f,0.29f,0f);
        PlaneRigidbody.inertiaTensor = new Vector3(1003f,1045f,58f);
        PlaneRigidbody.inertiaTensorRotation = Quaternion.AngleAxis(-9.112f, Vector3.forward);
        // Specification At Cruise without Ground Effect
        Airspeed0 = 9.600f; // Magnitude of ground speed [m/s]
        alpha0 = 1.459f; // Angle of attack [deg]
        CDp0 = 0.016f; // Parasitic drag [-]
        Cmw0 =-0.114f; // Pitching momentum [-]
        CLMAX = 1.700f;
        // Wing
        Sw = 18.816f; // Wing area of wing [m^2]
        bw = 26.679f; // Wing span [m]
        cMAC = 0.755f; // Mean aerodynamic chord [m]
        aw = 0.108f; // Wing Lift Slope [1/deg]
        hw = (0.323f-0.250f); // Length between Wing a.c. and c.g.
        ew = 0.986f; // Wing efficiency
        AR = (bw*bw)/Sw; // Aspect Ratio
        // Tail
        Downwash = false; // Conventional Tail: True, T-Tail: False
        St = 1.526f; // Wing area of tail
        at = 0.088f; // Tail Lift Slope [1/deg]
        lt = 3.200f; // Length between Tail a.c. and c.g.
        deMAX = 10.000f; // Maximum elevator angle
        tau = 1.000f; // Control surface angle of attack effectiveness [-]
        VH = (St*lt)/(Sw*cMAC); // Tail Volume
        // Fin
        drMAX = 10.000f; // Maximum rudder angle            
        // Ground Effect
        CGEMIN = 0.293f; // Minimum Ground Effect Coefficient [-]
        // Stability derivatives
        Cyb = -0.003555f; // [1/deg]
        Cyp = -0.455493f; // [1/rad]
        Cyr = 0.143466f; // [1/rad]
        Cydr = 0.000888f; // [1/deg]
        Clb = -0.004049f; // [1/deg]
        Clp = -0.829690f; // [1/rad]
        Clr = 0.227736f; // [1/rad]
        Cldr = 0.000016f; // [1/deg]
        Cnb = -0.000500f; // [1/deg]
        Cnp = -0.132307f; // [1/rad]
        Cnr = 0.000942f; // [1/rad]
        Cndr = -0.000106f; // [1/deg]
    }
}

XFLR5とFusion360を使って諸元を計算する方法はこちら

設計シートを使って諸元を計算する方法はこちら

設計シート
「設計シート」の記事一覧です。

ここまでが事前に準備しておくものである

objファイルをUnityにインポートする

ここからはUnityでの操作になる

BRSimulator for Gliderのプロジェクトを開き,Projectウィンドウに上で出力した.objファイルをドラッグ&ドロップする

InspectorウィンドウでScale Factorに0.001を設定する

インポートしたモデルをシーンに追加する

Projectウィンドウにある新機体のモデルをHierarchyウィンドウのPlaneの子オブジェクトにドラッグ&ドロップする

右クリック>Prehab>Unpack Completelyでプレハブを解除する

オブジェクトの親子関係を整理する

本体のゲームオブジェクトの子オブジェクトにラダーとエレベータのゲームオブジェクトを置く

本体のゲームオブジェクトのInspectorウィンドウ>Add ComponentからMesh Colliderをアタッチし,Convexにチェックを入れる

機体のオブジェクトの設定を行う

さらに本体のゲームオブジェクトのInspectorウィンドウ>Add ComponentからRigidBodyをアタッチし,Use Gravityにチェックを入れる

Massに関してはスクリプトで設定するのでいじらなくていい

さらに,プロジェクトウィンドウのAssets>ScriptにあるAerodynamicCalculator.csを本体のゲームオブジェクトにアタッチする

垂直尾翼と水平尾翼のオブジェクトの設定を行う

ラダーのゲームオブジェクトにRigidBody,Hinge Joint,Rudder.csをアタッチする

RigidBodyはMass,Drag,Angular Dragすべてに0を入力し,Use Gravityのチェックは入れない

Hinge JointはAnchorでラダーの回転軸の位置を設定し,Axisで回転軸の向きを設定する

エレベーターも同様にRigidBody,Hinge Joint,Elevator.csを追加し,エレベーターの回転軸を設定する

機体オブジェクトにカメラを追加する

プロジェクトウィンドウのAssets>GameObjectにあるFPSCameraとTPSCameraをHierarchyウィンドウのモデル本体のゲームオブジェクトの子オブジェクトにドラッグ&ドロップする

モデル選択画面のサムネ画像を撮影する

新しく実装する以外のモデルを非アクティブにし,ThumbnailCameraのInspectorウィンドウでDepthを100に設定し,モデル選択時のサムネ画像を撮影する(画面をスクショしてペイントで加工する)

モデル選択ボタンを追加する

作成したサムネ画像をプロジェクトウィンドウのAssets>Imageにドラッグ&ドロップし,InspectorウィンドウのTexture TypeをSprite (2D and UI)に設定する

ボタンのゲームオブジェクトを複製し,ImageのInspectorウィンドウのSource Imageに上で作ったSpriteを設定する

ModelSelectButton.csにプログラムを追加し,ButtonのInspectorウィンドウのOnclick()の数字を変更する

機体諸元を入力する

AerodynamicCalculator.csに上で準備した機体諸元を追加する

おわりに

BRSimulator for Gliderに新機体を実装するやり方について説明した

今後フライトシミュレーターに実装される機体が増えればいいなと思う

↓関連記事

Unity
質問・感想・意見などあれば気軽にTwitterのDMかコメントお願いします!
スポンサーリンク

コメント