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

Unity中按住Shift实现玩家冲刺/加速的问题求助及代码修复

修复玩家冲刺速度叠加与无法恢复的问题

你的核心问题是直接修改了walkSpeed变量且未做合理重置:每次按住Shift时,Update循环都会执行walkSpeed += sprintMultiplier,导致速度持续叠加;松开Shift后没有把速度还原回初始值,所以玩家一直保持高速。

以下是两种可靠的修复方案:

方案一:保留基础速度,动态计算移动速度(推荐)

这种方法不会修改原始的行走速度变量,而是根据冲刺状态动态计算当前移动速度,从根源避免叠加和重置问题。

修改后的完整代码:

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

public class PlayerMovement : MonoBehaviour
{
    public CharacterController controller;

    public float walkSpeed = 10f; // 基础行走速度,全程不直接修改
    public bool isSprinting;
    public float sprintMultiplier = 2f; // 建议设为2,代表冲刺速度是行走的2倍
    public float gravity = -9.81f;
    public float jump = 1f;

    public Transform groundCheck;
    public float groundDistance = 0.4f;
    public LayerMask groundMask;

    Vector3 velocity;
    bool isGrounded;

    void Update()
    {
        isGrounded = Physics.CheckSphere(groundCheck.position, groundDistance, groundMask);

        if (isGrounded && velocity.y < 0)
        {
            velocity.y = -2f;
        }

        // 简化冲刺状态判断
        isSprinting = Input.GetKey(KeyCode.LeftShift);

        // 移动计算:根据冲刺状态动态调整速度
        float x = Input.GetAxis("Horizontal");
        float z = Input.GetAxis("Vertical");
        Vector3 move = transform.right * x + transform.forward * z;
        
        // 关键改动:用基础速度乘以冲刺乘数,而非修改walkSpeed本身
        float currentSpeed = isSprinting ? walkSpeed * sprintMultiplier : walkSpeed;
        controller.Move(move * currentSpeed * Time.deltaTime);

        // 跳跃逻辑
        if (Input.GetButtonDown("Jump") && isGrounded)
        {
            velocity.y = Mathf.Sqrt(jump * -2f * gravity);
        }

        velocity.y += gravity * Time.deltaTime;
        controller.Move(velocity * Time.deltaTime);
    }    
}

方案二:重置速度回初始值

如果坚持要修改walkSpeed,需要在松开Shift时将其重置回初始值,同时避免每次Update都叠加速度:

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

public class PlayerMovement : MonoBehaviour
{
    public CharacterController controller;

    public float walkSpeed = 10f;
    private float baseWalkSpeed; // 专门存储初始行走速度
    public bool isSprinting;
    public float sprintMultiplier = 5f; // 注意数值,因为是直接叠加,建议不要过大
    public float gravity = -9.81f;
    public float jump = 1f;

    public Transform groundCheck;
    public float groundDistance = 0.4f;
    public LayerMask groundMask;

    Vector3 velocity;
    bool isGrounded;

    void Start()
    {
        baseWalkSpeed = walkSpeed; // 初始化时保存基础速度
    }

    void Update()
    {
        isGrounded = Physics.CheckSphere(groundCheck.position, groundDistance, groundMask);

        if (isGrounded && velocity.y < 0)
        {
            velocity.y = -2f;
        }

        float x = Input.GetAxis("Horizontal");
        float z = Input.GetAxis("Vertical");
        Vector3 move = transform.right * x + transform.forward * z;
        controller.Move(move * walkSpeed * Time.deltaTime);

        if (Input.GetButtonDown("Jump") && isGrounded)
        {
            velocity.y = Mathf.Sqrt(jump * -2f * gravity);
        }

        velocity.y += gravity * Time.deltaTime;
        controller.Move(velocity * Time.deltaTime);

        // 冲刺逻辑修改
        if (Input.GetKeyDown(KeyCode.LeftShift)) // 用GetKeyDown只触发一次叠加
        {
            isSprinting = true;
            walkSpeed += sprintMultiplier;
        }
        if (Input.GetKeyUp(KeyCode.LeftShift)) // 松开时重置回基础速度
        {
            isSprinting = false;
            walkSpeed = baseWalkSpeed;
        }
    }    
}

注意:方案二必须用GetKeyDown和GetKeyUp代替GetKey,否则每次Update都会执行速度叠加;同时要在Start方法中保存初始的walkSpeed,否则重置时会出错。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 00:01:29