预测刚体对象x秒后的位置。

4
假设你有一个移动的刚体对象(Rigidbody),通过Rigidbody.AddForceRigidbody.velocity给它添加力。该对象可以滚动撞击其他对象并改变方向。
我知道Extrapolation,但在这种情况下,几乎不可能使用某些公式来获取对象在x秒内的位置,因为对象可能会在过程中撞击其他对象并改变速度/方向。

Unity 2017引入了Physics.autoSimulationPhysics.Simulate来解决这个问题。对于2D物理,使用Physics2D.autoSimulationPhysics2D.Simulate。我所做的就是首先将Physics.autoSimulation设置为false,然后调用Physics.Simulate函数。


在我的例子中,我想知道给一个Rigidbody施加力后4秒它会在哪里,对于像1这样的小秒数似乎工作得很好。问题是,当我传入更大的数字,如5及以上到Simulate函数时,预测位置不准确。差别非常大。
为什么会出现这种情况?我该怎么解决?这个问题在Android设备上更严重。
我当前使用的Unity版本是Unity 2017.2.0b5
下面是我正在使用的示例代码。 guide游戏对象只是用来显示/展示预测位置。
public GameObject bulletPrefab;
public float forceSpeed = 50;

public GameObject guide;

// Use this for initialization
IEnumerator Start()
{
    //Disable Physics AutoSimulation
    Physics.autoSimulation = false;

    //Wait for game to start in the editor before moving on(NOT NECESSARY)
    yield return new WaitForSeconds(1);

    //Instantiate Bullet
    GameObject obj = Instantiate(bulletPrefab);

    Rigidbody bulletRigidbody = obj.GetComponent<Rigidbody>();

    //Calcuate force speed. (Shoot towards the x + axis)
    Vector3 tempForce = bulletRigidbody.transform.right;
    tempForce.y += 0.4f;
    Vector3 force = tempForce * forceSpeed;

    //Addforce to the Bullet
    bulletRigidbody.AddForce(force, ForceMode.Impulse);

    //yield break;
    //Predict where the Rigidbody will be in 4 seconds
    Vector3 futurePos = predictRigidBodyPosInTime(bulletRigidbody, 4f);//1.3f
    //Show us where that would be
    guide.transform.position = futurePos;
}

Vector3 predictRigidBodyPosInTime(Rigidbody sourceRigidbody, float timeInSec)
{
    //Get current Position
    Vector3 defaultPos = sourceRigidbody.position;

    Debug.Log("Predicting Future Pos from::: x " + defaultPos.x + " y:"
        + defaultPos.y + " z:" + defaultPos.z);

    //Simulate where it will be in x seconds
    Physics.Simulate(timeInSec);

    //Get future position
    Vector3 futurePos = sourceRigidbody.position;

    Debug.Log("DONE Predicting Future Pos::: x " + futurePos.x + " y:"
        + futurePos.y + " z:" + futurePos.z);

    //Re-enable Physics AutoSimulation and Reset position
    Physics.autoSimulation = true;
    sourceRigidbody.velocity = Vector3.zero;
    sourceRigidbody.useGravity = false;
    sourceRigidbody.position = defaultPos;

    return futurePos;
}
2个回答

4
你很幸运,值为1的情况下都能正常工作。你不应该将任何大于0.03的值传递给Physics.SimulatePhysics2D.Simulate函数。

当值大于0.03时,你需要将它分成几部分,然后在循环中使用Simulate函数。通过减少x时间并检查是否仍大于或等于Time.fixedDeltaTime来完成。

替换

Physics.Simulate(timeInSec);

使用

while (timeInSec >= Time.fixedDeltaTime)
{
    timeInSec -= Time.fixedDeltaTime;
    Physics.Simulate(Time.fixedDeltaTime);
}

你新的完整的 predictRigidBodyPosInTime 函数应该长成这样:

Vector3 predictRigidBodyPosInTime(Rigidbody sourceRigidbody, float timeInSec)
{
    //Get current Position
    Vector3 defaultPos = sourceRigidbody.position;

    Debug.Log("Predicting Future Pos from::: x " + defaultPos.x + " y:"
        + defaultPos.y + " z:" + defaultPos.z);

    //Simulate where it will be in x seconds
    while (timeInSec >= Time.fixedDeltaTime)
    {
        timeInSec -= Time.fixedDeltaTime;
        Physics.Simulate(Time.fixedDeltaTime);
    }

    //Get future position
    Vector3 futurePos = sourceRigidbody.position;

    Debug.Log("DONE Predicting Future Pos::: x " + futurePos.x + " y:"
        + futurePos.y + " z:" + futurePos.z);

    //Re-enable Physics AutoSimulation and Reset position
    Physics.autoSimulation = true;
    sourceRigidbody.velocity = Vector3.zero;
    sourceRigidbody.useGravity = false;
    sourceRigidbody.position = defaultPos;

    return futurePos;
}

0

我知道这是一个晚回复,但是如果有人想知道如何解决这个问题的话,我还是来回答一下。我阅读了关于刚体速度的文档,如果你将它添加到刚体的位置上,你将得到刚体在1秒后的位置,所以如果你获取速度,将其乘以你想要看到的未来秒数,然后将其添加到刚体的位置上,你就可以得到刚体在x秒后的位置,就像这样。

{
Vector3 PredictionPos(Rigidbody _TargetRb, float _predictiontime){

//get the rigidbodies velocity
Vector3 _targvelocity = _TargetRB.velocity;
//multiply it by the amount of seconds you want to see into the future
_targvelocity *= _predictiontime;
//add it to the rigidbodies position
_targvelocity += _TargetRB.position;
//Return the position of where the target will be in the amount of seconds you want to see into the future
Return _targvelocity;
}
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接