以x秒为单位预测刚体对象的位置
假设你有一个移动的Rigidbody
对象。 Force通过Rigidbody.AddForce
或Rigidbody.velocity
添加到此Object。 对象可以滚动命中另一个对象并改变方向。
我知道外推,但在这种情况下,几乎不可能使用一些公式来获得x秒内物体的位置,因为物体可以击中另一个物体并改变过程中的速度/方向。
Unity 2017引入了Physics.autoSimulation
和Physics.Simulate
来解决这个问题。 对于2D物理学,即Physics2D.autoSimulation
和Physics2D.Simulate
。 我所做的只是将Physics.autoSimulation
设置为false然后调用Physics.Simulate
函数。
在我的例子中,我想知道在为它添加力之后4
秒内Rigidbody
会在哪里,它似乎在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(); //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.03
任何值传递给Physics.Simulate
或Physics2D.Simulate
函数。
当值大于0.03
,您必须将其分成几部分,然后在循环中使用Simulate
函数。 在检查它是否仍然更多或等于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; }