【问题标题】:Inconsistent jumping in Unity depending on Y value根据 Y 值在 Unity 中跳跃不一致
【发布时间】:2018-08-31 09:34:39
【问题描述】:

我正在 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 左右。

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

【问题讨论】:

  • @AnLog 调试是什么意思?你的意思是在跳转语句中放Debug.Log("jump")?
  • 抱歉,我确实在移动设备上玩弄了手脚并发表了不完整的评论。我认为您应该在跳转部分添加一条 Debug.Log("jump") 行,以查看它是否在开始时仍然与地面接触时实际上没有多次跳跃。
  • 好的,这是一个聪明的主意。我会试试的。我确实看过互联网,它说在跳转语句的末尾添加 isGrounded = false ,所以我也会尝试。谢谢!编辑:我的代码中已经有 isGrounded = false ,所以我会更新问题中的代码。
  • @AnLog 好像只跳了一次。

标签: c# unity3d


【解决方案1】:

我通常做的是检查我是向上还是向下。我只接受地面检查是否向下。

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...

让我解释一下:

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

现在根据您的帧速率,与(几乎)常量 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...
    }
}

所以您只需在更新中处理所有输入逻辑,并在固定更新中执行其余逻辑。

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

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

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

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

【讨论】:

  • 感谢您的精彩回答!我查看了 Brackeys 的教程,其中之一,如何制作视频游戏系列,将输入放在 FixedUpdate 中,所以我认为这样做是可以的。但是,在他的另一篇教程中,输入和实际动作是在不同的脚本中。 WASD 运动有什么方法可以做到这一点,还是没关系?
  • 一般建议在Update() 中输入内容。东西不仅可以运行两次,您甚至可能会错过一次击键。当然,您也可以将 WASD 内容放入 Update 并在 FixedUpdate 中使用 A_downA_held 之类的布尔值。我做类似的事情,因为我有本地合作社(多个 Xbox360 控制器)
  • 我又做了一些测试,结果问题仍然存在。不知道为什么只是放在地上的时候Y值不一样。
  • 那么,是跳跃高度不同,还是跳跃后y位置不同? (玩家挖地几毫米)
  • 两者。有时在跳跃后静息 Y 值在 0.16 左右,它不会跳得很高,有时它是 ~0.23,当它确实跳得很高时。奇怪的是,玩家总是略微嵌入地面,但碰撞器看起来都很好,~0.16 和 ~0.23 之间没有视觉差异。
【解决方案2】:

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

【讨论】:

    猜你喜欢
    • 2019-10-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-08-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多