在 x 秒内预测刚体对象的位置
Predict the position of a Rigidbody Object in x second
假设您有一个 Rigidbody
移动的对象。通过 Rigidbody.AddForce
或 Rigidbody.velocity
向此对象添加力。该对象可以滚动撞击另一个对象并改变方向。
我知道 Extrapolation 但在这种情况下,几乎不可能使用某些公式在 x 秒内获得对象的位置,因为对象可以击中另一个对象并在此过程中更改speed/direction。
引入了 Unity 2017 Physics.autoSimulation
and Physics.Simulate
to solve this problem. For 2D physics, that is Physics2D.autoSimulation
and Physics2D.Simulate
。我所做的只是首先将 Physics.autoSimulation
设置为 false 然后调用 Physics.Simulate
函数。
在我的示例中,我想知道 Rigidbody
在对其施加力后 4
秒内的位置,它似乎在像 1
这样的微小秒内工作正常。问题是,当我将 5
及以上的更大数字传递给 Simulate
函数时,预测位置 不 准确。它的路途遥远。
为什么会发生这种情况,我该如何解决?此问题在 Android 台设备上更为严重。
我当前的Unity版本是Unity 2017.2.0b5.
下面是我正在使用的示例代码。 guide
游戏对象仅用于 display/show 预测位置。
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.03
的值传递给 Physics.Simulate
或 Physics2D.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;
}
我知道这是一个迟到的回复,但是,以防万一有人想知道如何解决这个问题。所以,我阅读了关于 rigidbody.velocity 的文档,如果你将它添加到刚体的位置,你将在 1 秒内得到刚体的位置,所以如果你得到速度,将它乘以你想要的秒数see in the future 然后你将它添加到刚体的位置你将在 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;
}
}
假设您有一个 Rigidbody
移动的对象。通过 Rigidbody.AddForce
或 Rigidbody.velocity
向此对象添加力。该对象可以滚动撞击另一个对象并改变方向。
我知道 Extrapolation 但在这种情况下,几乎不可能使用某些公式在 x 秒内获得对象的位置,因为对象可以击中另一个对象并在此过程中更改speed/direction。
引入了 Unity 2017 Physics.autoSimulation
and Physics.Simulate
to solve this problem. For 2D physics, that is Physics2D.autoSimulation
and Physics2D.Simulate
。我所做的只是首先将 Physics.autoSimulation
设置为 false 然后调用 Physics.Simulate
函数。
在我的示例中,我想知道 Rigidbody
在对其施加力后 4
秒内的位置,它似乎在像 1
这样的微小秒内工作正常。问题是,当我将 5
及以上的更大数字传递给 Simulate
函数时,预测位置 不 准确。它的路途遥远。
为什么会发生这种情况,我该如何解决?此问题在 Android 台设备上更为严重。
我当前的Unity版本是Unity 2017.2.0b5.
下面是我正在使用的示例代码。 guide
游戏对象仅用于 display/show 预测位置。
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.03
的值传递给 Physics.Simulate
或 Physics2D.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;
}
我知道这是一个迟到的回复,但是,以防万一有人想知道如何解决这个问题。所以,我阅读了关于 rigidbody.velocity 的文档,如果你将它添加到刚体的位置,你将在 1 秒内得到刚体的位置,所以如果你得到速度,将它乘以你想要的秒数see in the future 然后你将它添加到刚体的位置你将在 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;
}
}