C# 计算弹丸着陆距离和时间
我是Unity的新手,我正在制作小游戏来学习 我目前正在制作一个射击游戏,我有一个小问题(计算错误)。 每当玩家按下空格键时,我都会创建新的子弹(使用C# 计算弹丸着陆距离和时间,c#,unity3d,math,physics,C#,Unity3d,Math,Physics,我是Unity的新手,我正在制作小游戏来学习 我目前正在制作一个射击游戏,我有一个小问题(计算错误)。 每当玩家按下空格键时,我都会创建新的子弹(使用刚体)并改变其速度。 我试图计算子弹会落在哪里,但我的计算有点错误 我使用的是物理公式:dx=x0+V0*t+0.5*a*t^2来计算子弹何时落在哪里 这是我到目前为止写的: float g = Physics.gravity.y; print(transform.position.y); // it starts on 0.5 //Yt = Y0
刚体
)并改变其速度。
我试图计算子弹会落在哪里,但我的计算有点错误
我使用的是物理公式:dx=x0+V0*t+0.5*a*t^2
来计算子弹何时落在哪里
这是我到目前为止写的:
float g = Physics.gravity.y;
print(transform.position.y); // it starts on 0.5
//Yt = Y0 + 0.5 * g * t^2
float time = ((0.15f - transform.position.y) * 2) / g; // The bullet would land on y equals to 0.15 because its height
print("TIME: " + Mathf.Sqrt(time));
print("dX = " + 100 * Mathf.Sqrt(time));
应用速度:
if (Input.GetKeyDown(KeyCode.Space))
{
rb.velocity = new Vector3(0, 0, 100);
}
在这种情况下,时间是2.67125,dX是26.7125,但在unity inspector中,我看到一颗子弹移动了27.91713
你觉得有什么不对劲吗
下面是现场的子弹
不要手动执行此操作。只有当您可以访问Unity的源代码,但普通Joe却不能访问时,才应该手动进行计算。即使你在计算中得到了它,代码也可能随时中断 Unity 2017.1引入了
物理模拟
功能和物理自动模拟
属性<代码>物理。自动模拟用于禁用物理,然后调用物理。然后调用模拟
手动模拟物理并返回刚体对象将来的位置
你的着陆点是0.15。首先,使用physics.autoSimulation=false禁用物理
,使用velocity
或AddForce
功能向刚体添加力。放置物理.模拟(时间.固定时间)循环编码>并使其连续运行,直到到达着陆点或直到pos.y<0.15
变为true
。退出while
循环后,应获取新位置并将其存储在临时变量中。您现在可以使用physics.autoSimulation=true重新启用物理功能编码>并重置转换
实施超时也很有帮助,这样当弹丸在规定的时间内没有到达着陆点时,就可以脱离循环。这可以防止游戏中可能出现的无限循环
这是一个保存着着陆位置、旋转和时间结果的结构:
public struct PredictResult
{
public Vector3 position;
public Quaternion rotation;
public float landingTime;
}
这是执行着陆检查的功能。成功时返回true
,如果未在timeOutTime
中提供的时间内到达着陆点,则可能需要增加timeOutTime
变量
bool PredictRigidBodyLandPos(Rigidbody sourceRigidbody, Vector3 velocity, out PredictResult result)
{
//const float landingYPoint = 0.15f;
const float landingYPoint = -1.651335f;
//Disable Physics AutoSimulation
Physics.autoSimulation = false;
//Shoot the Bullet
sourceRigidbody.velocity = velocity;
//Get current Position and rotation
Vector3 defaultPos = sourceRigidbody.position;
Quaternion defaultRot = sourceRigidbody.rotation;
Debug.Log("Predicting Future Pos from::: x " + defaultPos.x + " y:"
+ defaultPos.y + " z:" + defaultPos.z);
//Exit after x seconds(In physics time) if Object does not land
float timeOutTime = 15f;
//The landing time that will be returned
float landingTime = 0;
//Determines if we landed successfully or not
bool landedSuccess = false;
//Simulate where it will be in x seconds
while (timeOutTime >= Time.fixedDeltaTime)
{
timeOutTime -= Time.fixedDeltaTime;
landingTime += Time.fixedDeltaTime;
Physics.Simulate(Time.fixedDeltaTime);
Vector3 pos = sourceRigidbody.position;
Debug.Log("Pos: " + pos.x + " " + pos.y + " " + pos.z);
//Check if we have landed then break out of the loop
if (pos.y < landingYPoint || Mathf.Approximately(pos.y, landingYPoint))
{
landedSuccess = true;
Debug.LogWarning("Landed");
break;
}
}
//Get future position and rotation and save them to output
Vector3 futurePos = sourceRigidbody.position;
Quaternion futureRot = sourceRigidbody.rotation;
result = new PredictResult();
result.position = futurePos;
result.rotation = futureRot;
result.landingTime = landingTime;
//Re-enable Physics AutoSimulation and Reset position and rotation
Physics.autoSimulation = true;
sourceRigidbody.velocity = Vector3.zero;
//sourceRigidbody.useGravity = false;
sourceRigidbody.transform.position = defaultPos;
sourceRigidbody.transform.rotation = defaultRot;
return landedSuccess;
}
按Space
键拍摄刚体,然后返回着陆距离
请注意,您说过它应该在pos.y时着陆。不要手动执行此操作。只有当您可以访问Unity的源代码,但普通Joe却不能访问时,才应该手动进行计算。即使你在计算中得到了它,代码也可能随时中断
Unity 2017.1引入了物理模拟
功能和物理自动模拟
属性<代码>物理。自动模拟
用于禁用物理,然后调用物理。然后调用模拟
手动模拟物理并返回刚体对象将来的位置
你的着陆点是0.15。首先,使用physics.autoSimulation=false禁用物理
,使用velocity
或AddForce
功能向刚体添加力。放置物理.模拟(时间.固定时间)循环编码>并使其连续运行,直到到达着陆点或直到pos.y<0.15
变为true
。退出while
循环后,应获取新位置并将其存储在临时变量中。您现在可以使用physics.autoSimulation=true重新启用物理功能编码>并重置转换
实施超时也很有帮助,这样当弹丸在规定的时间内没有到达着陆点时,就可以脱离循环。这可以防止游戏中可能出现的无限循环
这是一个保存着着陆位置、旋转和时间结果的结构:
public struct PredictResult
{
public Vector3 position;
public Quaternion rotation;
public float landingTime;
}
这是执行着陆检查的功能。成功时返回true
,如果未在timeOutTime
中提供的时间内到达着陆点,则可能需要增加timeOutTime
变量
bool PredictRigidBodyLandPos(Rigidbody sourceRigidbody, Vector3 velocity, out PredictResult result)
{
//const float landingYPoint = 0.15f;
const float landingYPoint = -1.651335f;
//Disable Physics AutoSimulation
Physics.autoSimulation = false;
//Shoot the Bullet
sourceRigidbody.velocity = velocity;
//Get current Position and rotation
Vector3 defaultPos = sourceRigidbody.position;
Quaternion defaultRot = sourceRigidbody.rotation;
Debug.Log("Predicting Future Pos from::: x " + defaultPos.x + " y:"
+ defaultPos.y + " z:" + defaultPos.z);
//Exit after x seconds(In physics time) if Object does not land
float timeOutTime = 15f;
//The landing time that will be returned
float landingTime = 0;
//Determines if we landed successfully or not
bool landedSuccess = false;
//Simulate where it will be in x seconds
while (timeOutTime >= Time.fixedDeltaTime)
{
timeOutTime -= Time.fixedDeltaTime;
landingTime += Time.fixedDeltaTime;
Physics.Simulate(Time.fixedDeltaTime);
Vector3 pos = sourceRigidbody.position;
Debug.Log("Pos: " + pos.x + " " + pos.y + " " + pos.z);
//Check if we have landed then break out of the loop
if (pos.y < landingYPoint || Mathf.Approximately(pos.y, landingYPoint))
{
landedSuccess = true;
Debug.LogWarning("Landed");
break;
}
}
//Get future position and rotation and save them to output
Vector3 futurePos = sourceRigidbody.position;
Quaternion futureRot = sourceRigidbody.rotation;
result = new PredictResult();
result.position = futurePos;
result.rotation = futureRot;
result.landingTime = landingTime;
//Re-enable Physics AutoSimulation and Reset position and rotation
Physics.autoSimulation = true;
sourceRigidbody.velocity = Vector3.zero;
//sourceRigidbody.useGravity = false;
sourceRigidbody.transform.position = defaultPos;
sourceRigidbody.transform.rotation = defaultRot;
return landedSuccess;
}
按Space
键拍摄刚体,然后返回着陆距离
请注意,您说过它应该在pos.y不是Op问题的直接答案时着陆,但这里它适用于任何遇到此线程但正在使用Rigidbody2D的人
使用Physics2D.simulationMode=SimulationMode2D.Script代码>而不是Physics.autoSimulation=false代码>当您想关闭物理自动模拟时
使用Physics2D.simulationMode=SimulationMode2D.FixedUpdate代码>而不是Physics.autoSimulation=true代码>要再次启用自动模拟时
模拟时使用Physics2D.Simulate(Time.fixeddedtime)代码>
供参考的正式文件:
这不是对Op问题的直接回答,但这里它适用于任何遇到此线程但正在使用Rigidbody2D的人
使用Physics2D.simulationMode=SimulationMode2D.Script代码>而不是Physics.autoSimulation=false代码>当您想关闭物理自动模拟时
使用Physics2D.simulationMode=SimulationMode2D.FixedUpdate代码>而不是Physics.autoSimulation=true代码>要再次启用自动模拟时
模拟时使用Physics2D.Simulate(Time.fixeddedtime)代码>
官方文件