Spaceflight 模拟器如何预测飞行路径?
How does Spaceflight simulator predict flight-paths?
我正在尝试使用 Unity 制作一款游戏,该游戏使用在轨火箭并可以转移到不同的行星,但我需要实时预测火箭路径,具体取决于当前 velocity/direction像 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);
但我不知道如何预测未来的时间点来给我轨道形状。
我试过 "speeding up the simulation" 和 Time.timeScale = 50;
但速度不够快。
我在某处读到我需要太阳系的副本 运行 独立形成统一更新,并从那里计算火箭轨迹,但我不知道如何处理。
在物理模拟方面我有点菜鸟所以你们中的一位天才可以帮忙吗?
这是您的代码实际执行的操作:
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 已经将原力乘以 Time.deltaTime。您在这里想要的是切换到 ForceMode.Impulse,或删除 deltaTime。
F = (Gravity * Mass) / distanceSqrMag;
forces = distance.normalized * -F;
Satelite.GetComponent<Rigidbody>().AddForce(forces, ForceMode.Force);
或者更好的是,假设 Mass 是卫星的质量,而引力不是一般常数,而是地球的局部引力。 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 预测位置的方法。当您拥有所需的所有计算能力时,无需花哨的计算。
如果你想要多个单体重力模拟,很简单。要么应用所有行星的引力,要么仅应用最近行星的引力并考虑其质量。如果你的行星少于十几个,我推荐前者。
您不需要圆锥曲线、高等数学或任何其他东西。你不是 kerbal space 程序。有时蛮力是最好的解决方案。
我正在尝试使用 Unity 制作一款游戏,该游戏使用在轨火箭并可以转移到不同的行星,但我需要实时预测火箭路径,具体取决于当前 velocity/direction像 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);
但我不知道如何预测未来的时间点来给我轨道形状。
我试过 "speeding up the simulation" 和 Time.timeScale = 50;
但速度不够快。
我在某处读到我需要太阳系的副本 运行 独立形成统一更新,并从那里计算火箭轨迹,但我不知道如何处理。
在物理模拟方面我有点菜鸟所以你们中的一位天才可以帮忙吗?
这是您的代码实际执行的操作:
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 已经将原力乘以 Time.deltaTime。您在这里想要的是切换到 ForceMode.Impulse,或删除 deltaTime。
F = (Gravity * Mass) / distanceSqrMag;
forces = distance.normalized * -F;
Satelite.GetComponent<Rigidbody>().AddForce(forces, ForceMode.Force);
或者更好的是,假设 Mass 是卫星的质量,而引力不是一般常数,而是地球的局部引力。 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 预测位置的方法。当您拥有所需的所有计算能力时,无需花哨的计算。
如果你想要多个单体重力模拟,很简单。要么应用所有行星的引力,要么仅应用最近行星的引力并考虑其质量。如果你的行星少于十几个,我推荐前者。
您不需要圆锥曲线、高等数学或任何其他东西。你不是 kerbal space 程序。有时蛮力是最好的解决方案。