2017-08-03 82 views
1

假设您有一个可移动的Rigidbody对象。强制通过Rigidbody.AddForceRigidbody.velocity添加到此对象。对象可以滚动另一个对象并改变方向。预测x秒内刚体对象的位置

我知道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

下面是我使用的示例代码。游戏对象仅用于显示/显示预测位置的位置。

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

你甚至很幸运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

感谢。这工作得很好。 – Programmer