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

Unity Character Controller跳跃功能失效问题求助

问题分析与修复方案

你的跳跃无响应问题主要来自方法调用顺序和输入检测逻辑的问题,以下是具体排查点和修复后的代码:

核心问题点

  • Update方法执行顺序错误:原代码中GravityMethod先于JumpMethod执行,GravityMethod里已经调用了controller.Move(velocity * Time.deltaTime),之后JumpMethod修改的velocity.y要到下一帧才会生效,导致跳跃指令被延迟或覆盖。
  • 跳跃输入检测逻辑错误:使用Input.GetKey会在按住空格时持续触发,导致跳跃速度被反复重置,应该用Input.GetKeyDown只在按下瞬间触发一次跳跃。
  • stamina判断逻辑错误:原代码判断stamina != 0(最大值永远不为0),应该判断当前耐力currentStamina > 0,否则 sprint 持续生效的逻辑不成立。
  • 地面检测潜在问题:需确保groundCheck的Transform位于玩家CharacterController底部(比如Y轴位置比控制器中心低,接近地面),同时Physics.CheckSphere的半径建议略小于CharacterController的radius,避免误判。

修复后的完整代码

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

public class PlayerMovement : MonoBehaviour
{
    // 移动速度设置
    private float movementSpeed;
    public float normalSpeed = 3f;
    public float sprintSpeed = 5f;

    // 耐力相关
    public float currentStamina;
    public float staminaUsageMultiplier = 2.5f;
    public float stamina = 100f;

    // 重力与跳跃
    public float gravity = -9.8f;
    public float jumpHeight = 3f;

    // 输入变量
    private float horInput;
    private float verInput;

    // 状态标记
    private bool isGrounded;

    // 组件引用
    private CharacterController controller;

    // 向量变量
    private Vector3 move;
    private Vector3 velocity;

    // 地面检测点
    public Transform groundCheck;

    // 地面层掩码
    public LayerMask groundLayer;

    private void Awake()
    {
        controller = GetComponent<CharacterController>();
    }

    void Start()
    {
        currentStamina = stamina;
    }

    void Update()
    {
        // 调整顺序:先检测地面,再处理跳跃,最后处理重力和移动
        CheckGroundStatus();
        JumpMethod();
        GravityMethod();
        MovementMethod();
    }

    // 单独抽离地面检测逻辑,便于调试
    void CheckGroundStatus()
    {
        isGrounded = Physics.CheckSphere(groundCheck.position, 0.4f, groundLayer);
        // 落地时重置垂直速度,防止无限叠加重力
        if (isGrounded && velocity.y < 0)
        {
            velocity.y = -2f;
        }
    }

    void MovementMethod()
    {
        horInput = Input.GetAxis("Horizontal");
        verInput = Input.GetAxis("Vertical");

        move = transform.forward * verInput + transform.right * horInput;
        controller.Move(move * movementSpeed * Time.deltaTime);

        // 修正stamina判断逻辑
        if (Input.GetKey(KeyCode.LeftShift) && currentStamina > 0)
        {
            movementSpeed = sprintSpeed;
            currentStamina -= staminaUsageMultiplier * Time.deltaTime;
            // 防止stamina变为负数
            currentStamina = Mathf.Clamp(currentStamina, 0, stamina);
        }
        else
        {
            movementSpeed = normalSpeed;
            // 耐力恢复逻辑(可选,根据需求添加)
            if (currentStamina < stamina)
            {
                currentStamina += staminaUsageMultiplier * 0.5f * Time.deltaTime;
            }
        }
    }

    void GravityMethod()
    {
        // 只有不在地面时才应用重力
        if (!isGrounded)
        {
            velocity.y += gravity * Time.deltaTime;
        }
        controller.Move(velocity * Time.deltaTime);
    }

    void JumpMethod()
    {
        // 使用GetKeyDown确保只触发一次跳跃
        if (Input.GetKeyDown(KeyCode.Space) && isGrounded)
        {
            velocity.y = Mathf.Sqrt(jumpHeight * -2f * gravity);
        }
    }
}

额外调试建议

  • 在CheckGroundStatus方法中添加Debug.Log(isGrounded),查看地面检测是否正常触发。
  • 检查groundLayer是否正确勾选了地面对象所在的层,确保没有误选其他层。
  • 验证groundCheck的位置:运行时选中groundCheck对象,查看其在场景中的位置是否符合预期。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 00:55:31