Spaceflight模拟器如何预测飞行路径?

时间:2019-09-18 16:06:32

标签: c# unity3d simulation physics orbit

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

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

public interface IMyClass
{
    bool NeedsMoreWork(Item item, out Part part);
    bool DoWork(Item item);
}

public class MyClass : IMyClass
{
    private ILogger log;

    public MyClass(ILogger log)
    {
        this.log = log;
    }

    public bool NeedsMoreWork(Item item, out Part part)
    {
        log.Debug($"Examining item {item.Id}");
        part = null;
        if (item.Completed())
        {
            log.Debug($"Item {item.Id} already completed.");
            return false;
        }
        part = item.GetNextPart();
        log.Debug($"Item {item.Id} needs work on part {part.Id}.");
        return true;            
    }

    public bool DoWork(Item item)
    {
        if (!item.NeedsMoreWork(item, out Part part))
            return false;
        log.Debug($"Starting work on part {part.Id}.");
        // Do work on part.
        log.Debug($"Work completed on part {part.Id}.");
        return true;
    }
}

[TestMethod]
public void TestDoWork()
{
    // Version with Configure():
    var subst1 = Substitute.ForPartsOf<MyClass>(Substitute.For<ILogger>());
    subst1.Configure()
        .NeedsMoreWork(Arg.Any<Item>(), out Arg.Any<Part>())
        .Returns(false);

    // Version with WhenForAnyArgs():
    var subst2 = Substitute.ForPartsOf<MyClass>(Substitute.For<ILogger>());
    subst2.WhenForAnyArgs(x => x.NeedsMoreWork(Arg.Any<Item>(), out Arg.Any<Part>())
        .Returns(false);
}

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

我尝试使用 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); “加快仿真速度”,但速度不够快。 我在某处读到我需要一份通过统一更新独立运行的太阳系的副本,然后从那里计算火箭的轨迹,但我不知道该如何处理。

物理模拟方面我有点菜鸟,所以你们其中的天才可以帮忙吗?

1 个答案:

答案 0 :(得分:2)

这是您的代码实际在做什么:

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;
}

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

不用担心在轨迹上会有所不同,这正是团结预测位置的方法。当您拥有所需的全部计算能力时,就无需花哨的计算。

如果您想要的不仅仅是一个人体重力模拟,那很简单。要么应用所有行星的重力,要么简单地考虑最近的行星的重力。如果您的行星少于十二个,我建议您使用前者。

您不需要圆锥曲线,高级数学或任何形式的数学。您不是路边空间计划。有时蛮力是最好的解决方案。