基于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
相关产品推荐
相关产品推荐

