统一飞机物理

时间:2018-04-08 10:39:58

标签: c# unity3d math air physics

我想制作一个简单的飞机控制器,整体看起来很小。我从飞机物理学看一些视频。统一制作一个简单的剧本,但如果我开始,我的飞机不能移动,或者如果我将阻力改为零,它就无法抬起。我尝试使用真实数据并从维基(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)。

1 个答案:

答案 0 :(得分:5)

因此,您的代码存在许多问题。我在下面概述了它们;

计算力量

  

问题: angleOfAttack = Vector3.Angle(Vector3.forward, rb.velocity);

  • Vector3.forwardrb.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=velocityC=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.uplift不正确。提升行为垂直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);
}