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

Unity C#实现角色冲刺蹲伏功能 速度不生效/蹲伏跳变问题

问题描述

预期实现功能:

  • 按下LeftShift键触发角色冲刺
  • 按下LeftControl键触发角色蹲伏

已验证正常的逻辑:

  • 按键检测无问题:按下Shift键时控制台可正常打印Sprint Triggered日志,按下蹲伏键时对应触发日志可正常输出

现存异常:

  • 按下Shift键后角色移动速度无任何变化
  • 按下蹲伏键时角色仅出现极快速的上跳动作,无法进入预期蹲伏状态
  • 已反复核查所有变量配置,确认参数设置无误,始终无法定位运动状态未按预期变更的原因

原实现代码:

public class SprintingCrouching : MonoBehaviour
{
    private PlayerMovement playerMovement;
    public float sprintSpeed = 10f;
    public float moveSpeed = 5f;
    public float crouchSpeed = 2f;
    private Transform look_rot;
    private float standHeight = 1.6f;
    private float crouchHeight = 1f;
    private bool isCrouching = false;
    // Start is called before the first frame update
    void Awake()
    {
        playerMovement = GetComponent<PlayerMovement>();
        look_rot = transform.GetChild(0);
    }

    // Update is called once per frame
    void Update()
    {
        SprintPlayer();
        Crouch();
        Debug.Log(playerMovement.speed);
    }
    void SprintPlayer()
    {
        if(Input.GetKeyDown(KeyCode.LeftShift))
        {
            Debug.Log("Sprint Triggered");
            playerMovement.speed = sprintSpeed;
        }
    }
    void Crouch()
    {
        if (Input.GetKeyDown(KeyCode.LeftControl))
        {
            Debug.Log("Crouch Triggered");
            look_rot.localPosition = new Vector3(0f, standHeight, 0f);
            playerMovement.speed = moveSpeed;
            isCrouching = false;
        }
        else
        {
            look_rot.localPosition = new Vector3(0f, crouchHeight, 0f);
            playerMovement.speed = moveSpeed;
            isCrouching = true;
        }
    }
}
问题根因

代码存在两处核心逻辑错误:

  1. 冲刺速度被强制覆盖:SprintPlayer()仅在按下Shift的单帧将速度设为冲刺值,后续每帧执行的Crouch()方法无论当前是什么状态,都会把速度强制重置为普通行走速度,冲刺设置完全不生效。
  2. 蹲伏判断逻辑完全颠倒:Crouch()使用仅触发单帧的GetKeyDown判断Ctrl按键,仅在按下Ctrl的那一帧设置为站立状态,其余所有帧(包括未按Ctrl、长按Ctrl的帧)都会强制进入蹲伏分支,导致角色高度反复跳变;同时分支内站立/蹲伏高度的赋值逻辑写反,完全不符合预期。
修复方案

将零散的状态赋值逻辑统一为每帧按优先级计算状态,使用GetKey做长按检测,修复后代码如下:

public class SprintingCrouching : MonoBehaviour
{
    private PlayerMovement playerMovement;
    public float sprintSpeed = 10f;
    public float moveSpeed = 5f;
    public float crouchSpeed = 2f;
    private Transform look_rot;
    private float standHeight = 1.6f;
    private float crouchHeight = 1f;
    private bool isCrouching = false;
    private bool isSprinting = false;
    
    void Awake()
    {
        playerMovement = GetComponent<PlayerMovement>();
        look_rot = transform.GetChild(0);
        // 初始化默认站立状态
        look_rot.localPosition = new Vector3(0f, standHeight, 0f);
        playerMovement.speed = moveSpeed;
    }

    void Update()
    {
        // 读取实时按键状态
        isSprinting = Input.GetKey(KeyCode.LeftShift);
        isCrouching = Input.GetKey(KeyCode.LeftControl);
        
        // 按优先级设置状态:蹲伏 > 冲刺 > 普通行走
        if (isCrouching)
        {
            look_rot.localPosition = new Vector3(0f, crouchHeight, 0f);
            playerMovement.speed = crouchSpeed;
        }
        else if (isSprinting)
        {
            look_rot.localPosition = new Vector3(0f, standHeight, 0f);
            playerMovement.speed = sprintSpeed;
        }
        else
        {
            look_rot.localPosition = new Vector3(0f, standHeight, 0f);
            playerMovement.speed = moveSpeed;
        }
        
        Debug.Log(playerMovement.speed);
    }
}

修复点说明

  • 将仅检测单帧按下的GetKeyDown替换为检测长按状态的GetKey,匹配冲刺、蹲伏需要持续保持的交互逻辑
  • 统一在每帧根据当前按键状态计算角色属性,按「蹲伏>冲刺>普通行走」的优先级设置视角高度和移动速度,彻底避免不同方法重复赋值互相覆盖的问题
  • 修正原逻辑中蹲伏/站立高度赋值颠倒的错误
  • 新增启动初始化逻辑,避免游戏运行第一帧视角高度异常

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 04:01:14