以x秒为单位预测刚体对象的位置

时间:2017-08-03 12:55:52

标签: c# unity3d rigid-bodies

假设您有一个移动的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 GameObject仅用于显示/显示预测位置的位置。

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

1 个答案:

答案 0 :(得分:3)

你很幸运1的价值在所有人身上都有效。您不应0.03以上的任何值传递给Physics.SimulatePhysics2D.Simulate函数。

当值高于0.03时,您必须将其分成几部分,然后在循环中使用Simulate函数。在检查 x 时间是否更多或等于Time.fixedDeltaTime时,应该减少 x 时间。

替换

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