假设您有一个移动的Rigidbody
对象。强制通过Rigidbody.AddForce
或Rigidbody.velocity
添加到此对象。对象可以滚动命中另一个对象并改变方向。
我知道Extrapolation但是在这种情况下,几乎不可能使用某些公式来获取对象在 x 秒内的位置,因为对象可以击中另一个对象并更改过程中的速度/方向。
Unity 2017引入了Physics.autoSimulation
和Physics.Simulate
来解决此问题。对于2D物理,即Physics2D.autoSimulation
和Physics2D.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;
}
答案 0 :(得分:3)
你很幸运1
的价值在所有人身上都有效。您不应将0.03
以上的任何值传递给Physics.Simulate
或Physics2D.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;
}