【问题标题】:How can I fix jumping in the air?我该如何解决在空中跳跃的问题?
【发布时间】:2020-11-07 23:26:15
【问题描述】:

我正在使用 Unity 制作 2D 平台游戏。我使用this 教程编写了这段代码,但做了一点改动。我想同时支持键盘和游戏手柄,所以我使用了新的输入系统。我已经定义了三个名为 GroundedRememeber、JumpPressedRemember 和 JumpPressedRememberTime 的变量,它们基本上像计时器一样工作,并检查玩家是否离开地面,然后玩家可以在靠近地面时跳跃而无需触摸它,我想用它代替著名的“groundCheck”。但问题是这些计时器不起作用,当我快速按下跳跃按钮时,即使在空中,玩家也可以永远跳跃。此外,如您所见,我添加了一个名为“groundLayers”的图层蒙版,让玩家只能在这种类型的物体上跳跃,但是当我在 Inspector 的“groundLayers”插槽中选择“Ground”时,玩家无法再跳跃.

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

public class PlayerController : MonoBehaviour, PlayerInputActions.IPlayerActions
 {
   private PlayerInputActions controls; 
   [SerializeField] LayerMask groundLayers;     
   private Rigidbody2D rb;
   private Animator anim;
   private bool facingRight = true;
   private Vector2 moveInput;
  [SerializeField] private float jumpForce;
    float JumpPressedRemember = 0;
   
   [SerializeField] float JumpPressedRememberTime = 0.2f;
    float GroundedRemember = 0;
     
   [SerializeField]  float GroundedRememberTime = 0.25f;  
   [SerializeField]  float HorizontalAcceleration = 1;
   [SerializeField] [Range(0, 1)] float HorizontalDampingBasic = 0.5f;
   [SerializeField] [Range(0, 1)] float HorizontalDampingWhenStopping = 0.5f;
   [SerializeField] [Range(0, 1)] float HorizontalDampingWhenTurning = 0.5f;
   [SerializeField] [Range(0, 1)] float JumpHeight = 0.5f;

   private void Awake() 
   {
      controls = new PlayerInputActions();

      controls.Player.SetCallbacks(this);
    }
     void Start()
    {
      rb = GetComponent<Rigidbody2D>();
      anim = GetComponent<Animator>();       
}
   void PlayerInputActions.IPlayerActions.OnMove(InputAction.CallbackContext context)
   {
      moveInput = context.ReadValue<Vector2>();
          
   }
    void Jump() {
     rb.AddForce(Vector2.up * jumpForce, ForceMode2D.Force);
     GroundedRemember = 0;
     JumpPressedRemember = 0;
   }

  bool TryJump() {
    if (GroundedRemember > 0) {
        Jump();
        return true;
    } else {
        JumpPressedRemember = JumpPressedRememberTime;
        return false;
    }
}
   void PlayerInputActions.IPlayerActions.OnJump(InputAction.CallbackContext context)
   {
       jumpForce = context.ReadValue<float>();
       switch (context.phase) {
            case InputActionPhase.Performed:
               TryJump();
               break;
       }
   }
  void FixedUpdate()
  {

   if(facingRight == false && moveInput.x > 0){
   
    Flip();
   
   }else if (facingRight == true && moveInput.x < 0){
    
    Flip();

   }
 }
    void Flip(){
    
    facingRight = !facingRight;
    Vector3 Scaler = transform.localScale;
    Scaler.x *= -1;
    transform.localScale = Scaler;
    
 }  
 void OnEnable()
 {
     controls.Enable();
 }
 
 void OnDisable()
{
    controls.Disable();
}
 void Update()
  {

   Vector2 GroundedBoxCheckPosition = (Vector2)transform.position + new Vector2(0, -0.01f);
   Vector2  GroundedBoxCheckScale = (Vector2)transform.localScale + new Vector2(-0.02f, 0);
   bool Grounded = Physics2D.OverlapBox(GroundedBoxCheckPosition, transform.localScale, 0, groundLayers);
    
    GroundedRemember -= Time.deltaTime;
    if (Grounded)
    {
      GroundedRemember = GroundedRememberTime;
    }

    JumpPressedRemember -= Time.deltaTime; 
  
    if ((JumpPressedRemember > 0)) {
      TryJump();
    }

    rb.velocity = new Vector2(rb.velocity.x, jumpForce);
    
     float HorizontalVelocity = rb.velocity.x;
      HorizontalVelocity += moveInput.x;
          
        if (Mathf.Abs(moveInput.x) < 0.01f)
            HorizontalVelocity *= Mathf.Pow(1f - HorizontalDampingWhenStopping, Time.deltaTime * 10f);
           else if (Mathf.Sign(moveInput.x) != Mathf.Sign(HorizontalVelocity))
           HorizontalVelocity *= Mathf.Pow(1f - HorizontalDampingWhenTurning, Time.deltaTime * 10f);
        else
            HorizontalVelocity *= Mathf.Pow(1f - HorizontalDampingBasic, Time.deltaTime * 10f);

        rb.velocity = new Vector2(HorizontalVelocity, rb.velocity.y);    
  }
}

【问题讨论】:

    标签: c# unity3d


    【解决方案1】:

    如果你知道玩家跳了多少,然后尝试为下一次跳跃添加延迟

    如果您知道如何使用协程,也许可以使用 Invoke() 函数。

    但我仍然建议使用地面检查,因为它实用且更容易,而且我看不出您不使用它的原因。

    【讨论】:

    • 感谢您的回答。如果我快速按下跳跃按钮,玩家可以永远跳跃。如您所见,对于地面检查,我附上了我在问题中使用的教程的链接。如果你看到它,你会发现我为什么要使用它。但是如果我想快速解释它,我不得不说我想使用它,因为它使游戏更具响应性。地面检查检查您是否在地面上,如果是,您可以跳跃,但如果您不在地面上,但距离地面很近(以厘米为单位),您无法跳跃,这是我的问题。
    猜你喜欢
    • 2021-05-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-25
    • 2020-02-14
    • 2021-08-19
    相关资源
    最近更新 更多