我想制作一个简单的飞机控制器,整体看起来很小。我从飞机物理学看一些视频。统一制作一个简单的剧本,但如果我开始,我的飞机不能移动,或者如果我将阻力改为零,它就无法抬起。我尝试使用真实数据并从维基(F22 Raptor)获取。对于我的游戏对象,我给出了刚体组件质量= 19670千克。 发动机推力= 2 * 116000.0f Newton。
private void calculateEnginePower()
{
EnginePower = engineThrust * ThrottleInput;
}
private void calculateForces()
{
angleOfAttack = Vector3.Angle(Vector3.forward, rb.velocity);
angleOfAttack = Mathf.Clamp(angleOfAttack, 0, 90);
coefficient = Mathf.Pow(1225.04f * rb.velocity.magnitude, 2) - 1; //M^2-2 where: M is mach.
if (coefficient > 0.0f)
coefficientLift = (4 * angleOfAttack) / Mathf.Sqrt(coefficient);
lift = 1.2754f * 0.5f * Mathf.Pow(rb.velocity.magnitude, 2) * coefficientLift * 78.04f; // densy1.2754 kg/m3, speed m/s , (F22)Wing area: 840 ft² (78.04 m²)
coefficientDrag = 0.021f;
rb.drag = coefficientDrag * 0.5f * Mathf.Pow(rb.velocity.magnitude,2) * 1.2754f * 78.04f;
rb.AddForce(transform.up * lift);
rb.AddForce(transform.forward * EnginePower);
}
使用这些公式:
升力: Lift formula 升力系数: Cl formula 拖动: Drag formula 对于阻力系数:我也使用维基数据(0.021f)。
答案 0 :(得分:5)
因此,您的代码存在许多问题。我在下面概述了它们;
计算力量
问题:
angleOfAttack = Vector3.Angle(Vector3.forward, rb.velocity);
Vector3.forward
和rb.velocity
都在世界空间中。 AoA
是机翼的局部和弦线与飞机velocity
之间的角度。 Vector3.Angle
将返回无符号角度。 AoA
必须在正面和负面方向上工作,否则将无法进行负面俯仰和反向飞行。
<强>解决方案:强> 将
rb.velocity
移至本地空间并使用三角函数求解AoA
。
// *flip sign(s) if necessary*
var localVelocity = transform.InverseTransformDirection(rb.velocity);
var angleOfAttack = Mathf.Atan2(-localVelocity.y, localVelocity.z);
<强>问题:强>
coefficient = Mathf.Pow(1225.04f * rb.velocity.magnitude, 2) - 1;
4α/sqrt(M^2−1)
是 M>的超声波系数。 1 即可。在零速度下,该等式将减少到sqrt(-1)
,这是一个将产生NaN
的虚数。马赫表示为M=V/C
,其中V=velocity
和C=the speed of sound
。您的1225.04f
常量必须为C
,单位为km / h,而不是 m / s 。您也是乘以而不是除以,如公式中所示。<强>解决方案:强> 用提升线理论简化你的方程式。
var aspectRatio = (wingSpan * wingSpan) / wingArea;
var inducedLift = angleOfAttack * (aspectRatio / (aspectRatio + 2f)) * 2f * Mathf.PI;
var inducedDrag = (inducedLift * inducedLift) / (aspectRatio * Mathf.PI);
来源: Aerospaceweb.org
<强>问题:强>
rb.drag = coefficientDrag * 0.5f * Pow(rb.velocity.mag,2) * 1.2754f * 78.04f;
rb.drag
。<强>解决方案:强> 将
rb.drag
属性设置为可能的最小值。
rb.drag = Mathf.Epsilon; // set in Awake
<强>问题:强>
rb.AddForce(transform.up * lift);
transform.up
对lift
不正确。提升行为垂直至velocity
,而drag
行为并行。
<强>解决方案:强> 通过将标准化的
lift
向量与飞机的横向方向交叉来计算velocity
方向,并将drag
对应velocity
。
// *flip sign(s) if necessary*
var dragDirection = -rb.velocity.normalized;
var liftDirection = Vector3.Cross(dragDirection, transform.right);
rb.AddForce(liftDirection * lift + dragDirection * drag);
你的升力方程看起来还不错,所以将它们放在一起会看起来像这样; (未测试)
public float wingSpan = 13.56f;
public float wingArea = 78.04f;
private float aspectRatio;
private void Awake ()
{
rb.drag = Mathf.Epsilon;
aspectRatio = (wingSpan * wingSpan) / wingArea;
}
private void calculateForces ()
{
// *flip sign(s) if necessary*
var localVelocity = transform.InverseTransformDirection(rb.velocity);
var angleOfAttack = Mathf.Atan2(-localVelocity.y, localVelocity.z);
// α * 2 * PI * (AR / AR + 2)
var inducedLift = angleOfAttack * (aspectRatio / (aspectRatio + 2f)) * 2f * Mathf.PI;
// CL ^ 2 / (AR * PI)
var inducedDrag = (inducedLift * inducedLift) / (aspectRatio * Mathf.PI);
// V ^ 2 * R * 0.5 * A
var pressure = rb.velocity.sqrMagnitude * 1.2754f * 0.5f * wingArea;
var lift = inducedLift * pressure;
var drag = (0.021f + inducedDrag) * pressure;
// *flip sign(s) if necessary*
var dragDirection = rb.velocity.normalized;
var liftDirection = Vector3.Cross(dragDirection, transform.right);
// Lift + Drag = Total Force
rb.AddForce(liftDirection * lift - dragDirection * drag);
rb.AddForce(transform.forward * EnginePower);
}