Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/arduino/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 计算弹丸着陆距离和时间_C#_Unity3d_Math_Physics - Fatal编程技术网

C# 计算弹丸着陆距离和时间

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

我是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 + 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)
  • 官方文件