【问题标题】:Unity aircraft physicsUnity飞机物理
【发布时间】:2018-09-17 21:50:52
【问题描述】:

我想做一个简单的飞行器控制器,统一起来看起来不太现实。我看了一些飞机物理学的视频。并统一制作一个简单的脚本,但是如果我开始,我的飞机无法移动,或者如果我将阻力更改为零,它就无法升起。我尝试使用真实数据并从 wiki(F22 Raptor) 获取。对于我的游戏对象,我给了刚体组件质量 = 19670 kg。 发动机推力 = 2 * 116000.0f 牛顿。

    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 对于阻力系数:我也使用了来自 wiki 的数据(0.021f)。

【问题讨论】:

  • 您是否尝试过调试以查看lift 和EnginePower 的值?你在哪里打电话calculateForces?
  • roll,pitch... 来自键盘和鼠标的输入,EnginePower 是一个简单的属性,我在 void Update 内的控制器中调用 Move 函数。 public void Move(float roll, float pitch, float yaw, float throttle) { // 将输入参数传入properties.s RollInput = roll;音高输入 = 音高;偏航输入 = 偏航;油门输入 = 油门;空气刹车 = 假;计算引擎功率();计算力();计算旋转(); }
  • 你也可以在Move函数中调用它进行调试。 private void debugThings() { Debug.Log("Aoa: " + angleOfAttack); Debug.Log("cL:" + coefficientLift); Debug.Log("电梯:" +电梯); Debug.Log("cD:" + coefficientDrag); Debug.Log("拖动:" + 拖动); Debug.Log("质量:" + rb.mass); Debug.Log("速度:" + rb.velocity.magnitude); Debug.DrawLine(rb.position, rb.velocity * 300, Color.red); }
  • lift 的典型值是什么?它们与飞机的重量相比如何? (g 在 Unity 单位中可能不是 9.81,但我不确定 - 最好的方法是通过实验找出答案)。根据this forum,drag 属性似乎有相当随意的单位(目前还不清楚它确切代表什么)

标签: c# unity3d math air physics


【解决方案1】:

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

计算力


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

  • Vector3.forward 和 rb.velocity 都在 世界空间 中。 AoA 是您机翼的局部弦线与飞机的velocity 之间的角度。
  • Vector3.Angle 将返回一个 unsigned 角度。 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。 Lift 垂直作用于velocity,而drag作用于平行。

解决方案: 通过将归一化的velocity 向量与飞机的横向方向相交来计算lift 方向,并将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);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-10-09
    • 2011-06-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-17
    • 1970-01-01
    相关资源
    最近更新 更多