【问题标题】:Why isn't this code working for double jumping in Unity?为什么这段代码不适用于 Unity 中的双跳?
【发布时间】:2022-01-22 07:08:35
【问题描述】:

我试图让我的角色能够在 2D Unity 项目中在空中/双跳时跳跃一次,下面是我的代码。玩家角色在空中可以跳一次但不能再跳一次,虽然我认为它在程序的眼中实际上是有效的,因为 jumpCounter 变量有时确实会增加到 1,但主要是直接增加到 2,所以我认为这是要做的事情即使我只按下一次空格键,也会在一帧中多次按下空格键?

代码:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerController2D : MonoBehaviour
{
    float xMovement = 0;
    float jumpValue = 0;
    Vector2 targetVelocity = new Vector2(0, 0);
    Rigidbody2D myRigidBody;
    public bool isGrounded = true;
    public int jumpCounter = 0;
    // Start is called before the first frame update
    void Start()
    {
        myRigidBody = GetComponent<Rigidbody2D>();
        myRigidBody.gravityScale = 8;
        //myRigidBody.simulated = false;
    }

    // Update is called once per frame
    void Update()
    {
        
    }

    void checkInputs()
    {
        xMovement = Input.GetAxis("Horizontal");
        jumpValue = 0;
        if (isGrounded)
        {
            jumpValue = Input.GetAxis("Jump");
            if (jumpValue > 0)
            {
                jumpCounter += 1;
            }
            if (jumpCounter >= 2)
                isGrounded = false;
        }
    }

    private void FixedUpdate()
    {
        checkInputs();
        myRigidBody.velocity = new Vector2(xMovement * 20, myRigidBody.velocity.y);
        myRigidBody.velocity = new Vector2(myRigidBody.velocity.x, jumpValue * 20);
    }

    private void OnCollisionEnter2D(Collision2D collision)
    {
        if (collision.transform.CompareTag("Ground"))
        {
            isGrounded = true;
            jumpCounter = 0;
        }
    }
}

【问题讨论】:

  • 你为什么用GetAxis跳转?

标签: c# unity3d


【解决方案1】:

原因是只要按住键,GetAxis 就会保持 >0。 FixedUpdate 事件每秒调用 50 次,因此即使是最快的按下也可能会导致两个跳跃在两个连续帧中立即发生。

至少有两种方法可以解决这个问题: 有一种机制,通过检查 GetAxis 何时再次为 0 来检查跳转是否实际完成,并且仅在其间发生时才允许第二次跳转。

更简单的解决方案是使用 Input.GetButtonDown。该方法只会在按下按钮时的单帧为 True,无论它被按住多长时间。不幸的是没有 GetAxisDown 什么的。

但是有一个陷阱:这会迫使您对 checkInputs() 调用使用 Update() 方法,而不是 FixedUpdate,因为它仅适用于单个渲染帧(与 Update() 同步),而不适用于整个渲染帧,通常更长的物理周期(物理周期是 FixedUpdate 与之同步的)。

【讨论】:

  • 感谢您的回答,但我对使用 Input.GetButtonDown 的代码的外观感到困惑?我试过把它放在各种地方来完成这项工作,但不知道如何正确地做到这一点。
【解决方案2】:

试试Input.GetKeyDown("space")。或Input.GetKeyDown(KeyCode.Space)

来自docs“从更新函数调用此函数,因为状态每帧都会重置。直到用户释放键并再次按下它才会返回true。”

我会检查这个:

void checkInputs()
{
    xMovement = Input.GetAxis("Horizontal");
    jumpValue = 0;
    if (isGrounded)
    {
        jumpValue = Input.GetKeyDown(KeyCode.space);
        if (jumpValue)
        {
            jumpCounter += 1;
        }
        if (jumpCounter >= 2)
            isGrounded = false;
    }
}

【讨论】:

  • 感谢您的回答,但该代码无法运行。 jumpValue 是一个整数,不能像 Input.GetKeyDown 返回的那样变成布尔值?
  • 哎呀,这是真的,你可以把它变成 bool 并检查 if (jumpValue) 是否按下了键。改变了答案。或者更好的是,您可以直接使用if (Input.GetKeyDown(KeyCode.space)) 进行检查,而根本不使用jumpValue 变量
  • 非常感谢,这行得通!如果有空间,是否有办法阻止玩家无限/不断向上跳跃?
猜你喜欢
  • 1970-01-01
  • 2019-11-20
  • 2016-04-14
  • 2020-11-13
  • 2016-04-08
  • 2021-06-21
  • 1970-01-01
  • 1970-01-01
  • 2022-12-20
相关资源
最近更新 更多