Unityを使って作成した鳥人間コンテストの滑空機部門を想定したフライトシミュレーターに新機体を実装するやり方についての開発者用の備忘録
実際に作成したフライトシミュレーターはこれ
keywords: Unity,物理演算,フライトシミュレーター,人力飛行機,微小擾乱理論
はじめに
Unityを使って作成した鳥人間コンテストの滑空機部門を想定したフライトシミュレーターに新機体を実装するやり方について説明する
Unityのバージョンは2020.3.8f1
Unityについては多くの入門サイトがあったが,今回特に参考にしたのはこちら
Unityの全般的な知識は上のサイトで,物理演算の基本については下のサイトを参考にした
≫Unity入門【初心者為の使い方講座】【実際にゲームを作って解説】 _ ゲームの作り方!
≫Unity カテゴリーの記事一覧 - エフアンダーバー
↓鳥人間コンテストのフライトシミュレーターの先駆者様
↓今回作成したプログラム
↓その他の解説記事
それではいってみよう
新機体実装の手順
BRSimulatorに新しい機体を実装するときは以下の手順で行う
- 3Dモデルを作って.objで出力する
- 機体諸元を計算する
- objファイルをUnityにインポートする
- インポートしたモデルをシーンに追加する
- オブジェクトの親子関係を整理してMesh Colliderを追加する
- 機体のオブジェクトの設定を行う
- 垂直尾翼と水平尾翼のオブジェクトの設定を行う
- 機体オブジェクトにカメラを追加する
- モデル選択画面のサムネ画像を撮影する
- モデル選択ボタンを追加する
- 機体諸元を入力する
それでは1つずつ説明していく
3Dモデルを作って.objで出力する
以下の条件を満たす3Dモデルを製作する
- 機体後方にx軸,機体上向きにy軸,左翼側にz軸
- エレベーター,ラダー,それ以外のすべて(本体),の3つのパーツ構成
- 主翼翼根の桁中心にモデルの原点
- 上の原点から計測したエレベーター,ラダーの回転軸の位置
- 上の原点から計測した重心位置および重心位置まわりの慣性モーメント
1.の条件は機体をきちんとした向きでゲーム内に配置するための必須条件である
座標系や回転についての詳細は下の記事を参照
2.,3.,4.の条件は舵面を動かすために必要な項目で,5.の条件は物理演算に必要になる
これらの条件を満たした3Dモデルを.obj形式で出力する
ボディを右クリック>メッシュで保存>形式:OBJ>リファインメント:高>OK
ちなみに.objファイルは色のデータを保持しないので,モデルの色は特に気にしなくていい
できればフライト中の翼がたわんだ状態のモデルのほうが現実味があって良い
機体諸元を計算する
機体の物理演算を行うために,以下の点に注意して機体諸元を計算する
- 諸元を計算するときに地面効果は考慮しない
- 地面効果は物理演算内で考慮する(\(C_{GE_{min}} = 0.2 \sim 0.4\))
- カウルや胴体の有害抗力係数はだいたい\((C_{D_{p}})_{body}=0.200\)として計算する
必要な諸元の一覧は以下のとおり
変数名 | 型 | 説明 | 単位 |
Rigidbody.mass | float | 全備重量 | kg |
Rigidbody.centerOfMass | Vector3 | 重心位置 | m |
Rigidbody.inertiaTensor | Vector3 | 重心まわりの主慣性モーメント | kg m^2 |
Rigidbody.inertiaTensorRotation | Quaternion | 慣性主軸への回転を表すクォータニオン | - |
Airspeed0 | float | 設計速度 | m/s |
alpha0 | float | 設計迎角 | deg |
CDp0 | float | 全機有害抗力係数の最小値 | - |
Cmw0 | float | 主翼空力中心回りの主翼ピッチングモーメント係数 | - |
CLMAX | float | 主翼および尾翼の最大揚力係数(共通) | - |
Sw | float | 主翼翼面積 | m^2 |
bw | float | 主翼翼幅 | m |
cMAC | float | 主翼平均空力翼弦長 | m |
aw | float | 主翼三次元揚力傾斜 | 1/deg |
hw | float | 主翼空力中心と全機重心の距離(cMACで無次元化) | - |
ew | float | 主翼翼効率(楕円翼を1としたときの誘導抗力の大きさ) | - |
Downwash | bool | 吹きおろしの計算を行うかどうか(通常配置: true,T字尾翼: false) | - |
St | float | 水平尾翼面積 | m^2 |
at | float | 水平尾翼三次元揚力傾斜 | 1/deg |
lt | float | 水平尾翼空力中心と全機重心の距離 | m |
deMAX | float | エレベーターの最大舵角 | deg |
tau | float | 舵面の効きを表す係数(白本:p.83) | - |
drMAX | float | ラダーの最大舵角 | deg |
CGEMIN | float | 地面効果係数の最小値(0<CGEMIN<1) | - |
Cyb,Clb,Cnb | float | 横滑りに関する安定微係数 | 1/deg |
Cyp, Clp, Cnp | float | ロール角速度に関する安定微係数 | 1/rad |
Cyr,Clr,Cnr | float | ヨー角速度に関する安定微係数 | 1/rad |
Cydr,Cldr,Cndr | float | ラダー舵角に関する安定微係数 | 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に新機体を実装するやり方について説明した
今後フライトシミュレーターに実装される機体が増えればいいなと思う
↓関連記事
コメント