You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Unity新输入系统,如何实现按按键时长控制跳跃高度?

用Unity新输入系统实现按按键时长控制跳跃高度

要实现按按键时长控制跳跃高度,核心逻辑是按下跳跃键时给初始起跳力,按住期间持续施加向上的力,直到松开按键或者达到设定的最大跳跃速度。结合你的现有代码,我给你调整出了初学者能轻松理解的实现方案:


1. 新增控制变量

在PlayerController类里添加几个可序列化变量,方便你在Unity编辑器里直观调整数值:

[SerializeField] float moveSpeed = 10f;
[SerializeField] float baseJumpForce = 12f; // 初始起跳的基础力(快速按跳的最低高度)
[SerializeField] float maxJumpForce = 20f; // 最大上升速度上限(防止按住跳得过高)
[SerializeField] float holdJumpAddForce = 2f; // 按住时每帧额外施加的力(控制高度增长速度)
[SerializeField] Rigidbody2D rb;
[SerializeField] Collider2D groundCheck;

Vector2 moveInput;
bool isMoving;
bool isGrounded;
bool isHoldingJump; // 标记是否正按住跳跃键

2. 修改跳跃输入回调

原来的OnJump只处理了按键按下瞬间,现在要区分按下和松开两种状态:

void OnJump(InputValue button)
{
    isGrounded = groundCheck.IsTouchingLayers(LayerMask.GetMask("Ground"));

    // 按键按下时触发初始起跳
    if (button.isPressed && isGrounded)
    {
        // 直接设置y轴速度,避免叠加下落速度导致跳跃高度不稳定
        rb.velocity = new Vector2(rb.velocity.x, baseJumpForce);
        isHoldingJump = true;
    }
    // 按键松开时停止持续加力
    else if (!button.isPressed)
    {
        isHoldingJump = false;
    }
}

3. 添加物理帧的持续跳跃逻辑

Unity的物理操作建议放在FixedUpdate里执行,避免帧率波动影响手感:

private void FixedUpdate()
{
    // 仅在按住跳跃键、处于上升阶段、且未达到最大速度时,持续加力
    if (isHoldingJump && rb.velocity.y > 0 && rb.velocity.y < maxJumpForce)
    {
        rb.AddForce(Vector2.up * holdJumpAddForce, ForceMode2D.Force);
    }

    // 落地时重置跳跃状态,避免空中误触发
    if (isGrounded)
    {
        isHoldingJump = false;
    }
}

4. 同步落地判断逻辑

在Update里同步更新落地状态,确保逻辑一致性:

void Update()
{
    isGrounded = groundCheck.IsTouchingLayers(LayerMask.GetMask("Ground"));
    Run();
    Flip();
}

完整修改后的代码

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

public class PlayerController : MonoBehaviour
{
    [SerializeField] float moveSpeed = 10f;
    [SerializeField] float baseJumpForce = 12f;
    [SerializeField] float maxJumpForce = 20f;
    [SerializeField] float holdJumpAddForce = 2f;
    [SerializeField] Rigidbody2D rb;
    [SerializeField] Collider2D groundCheck;

    Vector2 moveInput;
    bool isMoving;
    bool isGrounded;
    bool isHoldingJump;

    void Update()
    {
        isGrounded = groundCheck.IsTouchingLayers(LayerMask.GetMask("Ground"));
        Run();
        Flip();
    }

    private void FixedUpdate()
    {
        if (isHoldingJump && rb.velocity.y > 0 && rb.velocity.y < maxJumpForce)
        {
            rb.AddForce(Vector2.up * holdJumpAddForce, ForceMode2D.Force);
        }

        if (isGrounded)
        {
            isHoldingJump = false;
        }
    }

    void OnMove(InputValue value)
    {
        moveInput = value.Get<Vector2>();
    }

    void OnJump(InputValue button)
    {
        isGrounded = groundCheck.IsTouchingLayers(LayerMask.GetMask("Ground"));

        if (button.isPressed && isGrounded)
        {
            rb.velocity = new Vector2(rb.velocity.x, baseJumpForce);
            isHoldingJump = true;
        }
        else if (!button.isPressed)
        {
            isHoldingJump = false;
        }
    }

    void Run()
    {
        Vector2 runVelocity = new Vector2(moveInput.x * moveSpeed, rb.velocity.y);
        rb.velocity = runVelocity;
    }

    void Flip()
    {
        isMoving = Mathf.Abs(rb.velocity.x) > Mathf.Epsilon;

        if (isMoving)
        {
            transform.localScale = new Vector2(Mathf.Sign(rb.velocity.x), 1f);
        }
    }
}

关键逻辑说明

  • 初始跳跃用rb.velocity直接设置y轴速度,避免叠加下落速度导致跳跃高度不稳定
  • 持续加力用AddForce,符合物理引擎逻辑,手感更自然
  • 通过maxJumpForce限制最大上升速度,防止按住太久跳得超出预期
  • 仅在rb.velocity.y > 0时加力,确保只在上升阶段生效,不会影响下落过程

内容的提问来源于stack exchange,提问作者Lordvanan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 05:43:24