取决于Y值,Unity中的跳跃不一致

时间:2018-08-31 09:34:39

标签: c# unity3d

我正在Unity中制作游戏,您可以在其中移动WASD并有跳跃的空间。这是我的代码:

using UnityEngine;

public class PlayerMovement : MonoBehaviour {

    public Rigidbody rb;
    public bool canJump;

    void FixedUpdate () {
        if (Input.GetKey("w"))
        {
            rb.AddForce(0, 0, 750 * Time.deltaTime, ForceMode.Acceleration);
        }

        if (Input.GetKey("a"))
        {
            rb.AddForce(-750 * Time.deltaTime, 0, 0, ForceMode.Acceleration);
        }

        if (Input.GetKey("s"))
        {
            rb.AddForce(0, 0, -750 * Time.deltaTime, ForceMode.Acceleration);
        }

        if (Input.GetKey("d"))
        {
            rb.AddForce(750 * Time.deltaTime, 0, 0, ForceMode.Acceleration);
        }

        if (canJump)
        {
            if (Input.GetKeyDown("space"))
            {
                rb.AddForce(0, 10, 0, ForceMode.VelocityChange);
                Debug.Log("jump");
                canJump = false;
            }
        }

        Vector3 v = rb.velocity;
        v.y = 0;
        v = Vector3.ClampMagnitude(v, 6);
        v.y = rb.velocity.y;
        rb.velocity = v;
    }

    void OnCollisionEnter(Collision other)
    {
        if (other.gameObject.name == "Ground")
        {
            canJump = true;
        }
    }

    void OnCollisionExit(Collision other)
    {
        if (other.gameObject.name == "Ground")
        {
            canJump = false;
        }
    }
}

但是,当我跳时,它有时会跳得很高,有时甚至一点都跳不起来。我测试了按住空格键是否有任何作用,没有。我已经尝试过使用ForceMode.Impulse和ForceMode.VelocityChange,但是跳转仍然不一致。

我还注意到,玩家在地板上的Y值约为0.23时才跳到空中。像这样,它也可以是〜0.16,并且根本不会跳得很高。

这是〜0.16 0.16 这是〜0.23 0.23

最低的跳跃使它的Y值达到〜0.7,但是最高的跳跃使它的价值达到4.83左右。

如果有人有任何想法,我将非常感激。

2 个答案:

答案 0 :(得分:4)

我通常要做的是检查我是向上还是向下。我只接受地面检查,如果我向下走。

void OnCollisionEnter(Collision other)
{
    if (other.gameObject.name == "Ground" && rb.velocity.y < 0)
    {
        canJump = true;
    }
}

但是,您使用getKeyDOWN并不是要占用空间等。

所以我接下来要推荐的是:在跳跃之前将Velocity.y设置为0。

if (Input.GetKeyDown("space"))
{
    Vector3 vel = rb.velocity;
    vel.y = 0;
    rb.velocity = vel;
    rb.AddForce(0, 10, 0, ForceMode.VelocityChange);
    // ...
}

编辑:等等,我的第一个念头是“他使用getKey并保留了空格”,第二个念头是:“他错过了Time.deltaTime”。但是现在我看到了:

您在FixedUpdate中使用了Input.Get...

让我解释一下:

在调用所有Update之前评估所有输入。 As you can see in the execution Order在更新之前就已处理Input事件。

现在,根据(取决于)帧速率,与(几乎)恒定的FixedUpdate相比,Update被频繁或很少调用。

因此,在Update次调用之间,FixedUpdateUpdate可以多次调用。这意味着输入事件只运行了一次。

所以我不得不假设Input.GetKeyDown(Key.SPACE)在多个FixedUpdates中都是正确的!

轻松修复:

bool jump_pressed = false;

void Update()
{
    if(Input.GetKeyDown("space"))
    {
        jump_pressed = true;
    }
    if(Input.GetKeyUp("space"))
    {
        jump_pressed = false;
    }
}

void FixedUpdate()
{
    if(jump_pressed)
    {
        jump_pressed = false;
        rb.AddForce(0, 10, 0, ForceMode.VelocityChange);
        // etc...
    }
}

因此,您只需处理Update中的所有Input逻辑,然后在固定Update中执行其余的逻辑。

当然,在FixedUpdate中必须将jump_pressed设置为false,因为否则它将保持为多个FixedUpdates。

edit2 :我再次查看了您的代码。无论做什么,无论是在FixedUpdate还是Update中,都不要在Time.deltaTime中使用AddForce

AddForce将操纵速度。在每个PhysicsUpdate中使用速度来移动变换。但是PhysicsUpdate / FixedUpdate尝试以(几乎)固定的速率运行,而Time.deltaTime为您提供了最后一个(更新)帧的经过时间。

如果您自己移动转换(position += ...)-使用Time.deltaTime。但是在使用AddForce时不要使用它。

答案 1 :(得分:0)

好吧,如果您需要此功能来紧急修复。抓住统一的默认FPS角色并探索其属性和组件,并尝试对您自己的对象执行相同的操作。您稍后可以详细介绍