为了账号安全,请及时绑定邮箱和手机立即绑定

Unity 中根据 Y 值不一致的跳跃

Unity 中根据 Y 值不一致的跳跃

C#
慕神8447489 2021-12-25 16:30:34
我正在 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.23最低的跳跃使其 Y 值达到 ~0.7,但最高的跳跃使其达到 4.83 左右。如果有人有任何想法,我将不胜感激。
查看完整描述

2 回答

?
白板的微信

TA贡献1883条经验 获得超3个赞

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


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”。但现在我看到了:


您Input.Get...在 FixedUpdate 中使用过!


让我解释:


在Update调用所有s之前评估所有输入。 正如您在执行顺序中看到的,输入事件在更新之前被处理。


现在,根据您的帧速率,与(几乎)恒定的 FixedUpdate 相比,Update 会经常或很少被调用。


所以 FixedUpdate 可以在Update调用之间多次调用。这意味着输入事件运行一次。


所以我必须假设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 逻辑,并在固定更新中执行其余部分。


当然,在 FixedUpdate 中 jump_pressed 需要设置为 false,因为否则它会在多个 FixedUpdates 中保持 true。


edit2:我又看了你的代码。无论你做什么,无论是在 FixedUpdate 还是 Update 中,都不要使用Time.deltaTimein AddForce.


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


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


查看完整回答
反对 回复 2021-12-25
?
慕雪6442864

TA贡献1812条经验 获得超5个赞

好的,如果你需要这个来紧急修复。获取 unity 默认 FPS 角色并探索其属性和组件,并尝试对您自己的对象执行相同操作。你可以稍后再详谈


查看完整回答
反对 回复 2021-12-25
  • 2 回答
  • 0 关注
  • 398 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信