【问题标题】:How does Spaceflight simulator predict flight-paths?Spaceflight 模拟器如何预测飞行路径?
【发布时间】:2020-01-19 15:37:51
【问题描述】:

我正在尝试使用 Unity 制作一款游戏,该游戏使用在轨火箭并且可以过渡到不同的行星,但我需要实时预测火箭路径,具体取决于火箭分配的当前速度/方向就像spaceflight simulator 一样。

在向刚体添加重力时,我设法获得了逼真的物理和轨道:

    var sateliteCords = Satelite.transform.position;
    var planetCords = gameObject.transform.position;
    var distance = sateliteCords - planetCords;
    distanceFromSatelite = Vector3.Distance(Satelite.transform.position, gameObject.transform.position);
    F = (Gravity * Mass) / Mathf.Pow(distanceFromSatelite,2);
    forces = (distance / Mathf.Sqrt(Mathf.Pow(distance.x, 2)+ Mathf.Pow(distance.y, 2)+ Mathf.Pow(distance.z, 2))) * -F;
    Satelite.GetComponent<Rigidbody>().AddForce(forces * Time.deltaTime, ForceMode.Force);

但我不知道如何预测未来的时间点来给我轨道形状。

我试过用Time.timeScale = 50;“加速模拟”,但速度还不够快。 我在某处读到,我需要一份太阳系的副本,从统一更新中独立运行,并从那里计算火箭轨迹,但我不知道如何处理。

在物理模拟方面我有点菜鸟,所以请各位天才帮忙?

【问题讨论】:

  • 您可以并行模拟物理,但 1. Unity 不支持,因此您必须实现自己的物理引擎,并且 2. 它可能是不必要的计算密集型。更好的方法是使用patched conic approximation 来近似轨道轨迹。我不知道这方面的任何规范指南,但这是我在谷歌上找到的幻灯片,可以帮助您入门:maia.ub.edu/dsg/wsem/documents/PatchedConics.pdf
  • 如果你能把这个问题分解成更小的部分,我们可能可以回答这些部分,但正如所写的那样,我想说这个问题太宽泛了。从头开始编写一个完整的补丁圆锥逼近器对于一个答案来说太宽泛了。
  • @Ruzihm Unity 实际上确实现在支持。自 2018.3 起实施。见Multi-Scene Physics on this page。 ---关于实施指南,我也不知道,但我没有研究过。如果您查看 KSP(Kerbal Space Program),可能会有一些关于它的博文。
  • @XenoRo 整洁!我不知道它的存在。进一步看,您似乎可以使用它来模拟当前Update 调用中的多个时间步长。不确定它的性能如何,但这可以解决问题!
  • @Ruzihm 非常感谢您提供的信息,我找到了一个更简单的解决方案,但我会在未来研究修补圆锥近似,因为我确实想开始学习一些天体物理学和其他东西(大多数它仍然在我的头上)

标签: c# unity3d simulation physics orbit


【解决方案1】:

这是您的代码实际执行的操作:

var sateliteCords = Satelite.transform.position;
var planetCords = gameObject.transform.position;
var distance = sateliteCords - planetCords;
distanceFromSatelite = distance.magnitude;

F = (Gravity * Mass) / Mathf.Pow(distanceFromSatelite,2);
forces = distance / distanceFromSatellite * -F;
Satelite.GetComponent<Rigidbody>().AddForce(forces * Time.deltaTime, ForceMode.Force);

您可以通过以下方式进一步减少它:

var distance = sateliteCords - planetCords;
distanceSqrMag = distance.sqrMagnitude;

F = (Gravity * Mass) / distanceSqrMag;
forces = distance.normalized * -F;
Satelite.GetComponent<Rigidbody>().AddForce(forces * Time.deltaTime, ForceMode.Force);

现在代码更简单了,我可以找到一个关键错误。 ForceMode.Force 已经将 Force 乘以 Time.deltaTime。您想要在这里切换到 ForceMode.Impulse,或删除 deltaTime。

F = (Gravity * Mass) / distanceSqrMag;
forces = distance.normalized * -F;
Satelite.GetComponent<Rigidbody>().AddForce(forces, ForceMode.Force);

或者更好的是,假设质量是卫星的质量,而重力不是一般常数,而只是地球的局部重力。 ForceMode.Force 将力除以它所施加的刚体的质量。

F = Gravity / distanceSqrMag;
forces = distance.normalized * -F;
Satelite.GetComponent<Rigidbody>().AddForce(forces, ForceMode.Acceleration);

现在一切都结束了,你可以通过做类似的事情来做一个非常简单的近似

var currentPos = _rigidBody.position;
var prevPos = currentPos;
var currentVelocity = _rigidBody.velocity;
var planetCords = gameObject.transform.position;

for (int i = 0; i < stepCount; i++)
{
    var distance = planetCords - currentPos;

    var forceMag = Gravity / distance.sqrMagnitude;
    forces = distance.normalized * forceMag;
    currentVelocity  += forces * Time.fixedDeltaTime;

    currentPos += currentVelocity * Time.fixedDeltaTime;

    //Replace by a TrailRenderer you reset each frame
    Debug.DrawLine(prevPos, currentPos, Color.Red, Time.deltaTime);
    prevPos = currentPos;
}

请注意,此代码未经测试,我可能在这里或那里犯了一个错误,但这就是它的要点。

不用担心轨迹会有任何差异,这正是 unity 用来预测位置的。当您拥有所需的所有计算能力时,无需进行花哨的计算。

如果您想要不止一个实体的重力模拟,这很简单。要么应用所有行星的引力,要么简单地考虑最近行星的引力(考虑其质量)。如果你的行星少于十二个,我推荐前者。

您不需要圆锥曲线、高级数学或任何其他。你不是坎巴拉太空计划。有时蛮力是最好的解决方案。

【讨论】:

  • 效果很好!我不敢相信我的电脑生成这么多积分的速度有多快!太感谢了!!你救了我这么多头痛:)
  • 啊,我以为提问者是在询问涉及 n 个物体的长距离。很好的答案。
  • 请注意:在没有阻力(即脱离大气层)的环境中,可以使用轨道数学确定性地(无近似值)计算。然后,您可以通过使用您选择的技术近似路径来显示线条(提示:基于近点和远点的贝塞尔路径效果很好)。这样就不必对力和位置进行重复计算,从而节省了性能。基本上,您消除了近似值的物理方面;这是最重的。见Orbital Eccentricity
  • KSP(Kerbal Space Program)就是这样做的。我强烈怀疑这也是 Spaceflight Simulator 的做法。 --- 缺点是它只能处理一个行星/轨道体。 N 体物理变得更加复杂,并且是更广泛使用物理近似的地方。
  • @XenoRo 问题是这不适用于 n 体,我相信数学变得更加复杂。它还需要用这个数学预测替换物理引擎,这很简单,但可能会干扰他的游戏中的碰撞或其他力。另一个问题是实施阻力,并在每次施加力时重新计算轨道。
猜你喜欢
  • 1970-01-01
  • 2012-01-02
  • 2010-12-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-08-29
  • 2010-10-14
  • 2015-05-02
相关资源
最近更新 更多