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

Unity PlayerMovement脚本蹲伏失效 滑铲冲刺功能正常

问题根因

蹲伏移速不生效是三个核心逻辑错误导致的:

  1. StateHandler() 状态判断的分支写法和顺序有问题:蹲伏判断用了独立if而非互斥的else if,后面的滑铲判断也没加sliding状态的前置校验。只要之前开过冲刺、sprinting标记没重置,按住蹲伏时就会直接命中滑铲分支,把刚设置的crouchSpeed覆盖成slideSpeed。
  2. 蹲伏、滑铲的触发逻辑重复写了三处:MyInput()里一套、Update()里一套、StateHandler()里又改了一遍状态,逻辑互相覆盖,状态标记乱跳。
  3. 松开蹲伏键时不管当前是蹲伏还是滑铲,直接把sliding设为false,也没重置sprinting标记,下次按蹲伏很容易误判成滑铲。
修复方案
  • 调整StateHandler()的判断逻辑,按状态优先级从高到低用if-else if做互斥判断,顺序为:滑铲 > 蹲伏 > 冲刺 > 行走 > 空中,滑铲分支必须校验sliding为true才进入。
  • 删除分散在各处的重复蹲伏/滑铲触发逻辑,把按键响应、角色缩放、状态切换统一放到MyInput()里处理,避免逻辑冲突。
  • 补全状态重置逻辑:进入蹲伏时强制取消冲刺标记,松开蹲伏键时区分当前是滑铲还是普通蹲伏,执行对应恢复逻辑。
核心修改代码

首先替换原有的StateHandler()方法:

private void StateHandler()
{
    // 最高优先级:滑铲状态
    if (sliding)
    {
        state = MovementState.sliding;
        moveSpeed = slideSpeed;
    }
    // 普通蹲伏:不在滑铲状态时按蹲伏键进入
    else if (Input.GetKey(crouchKey))
    {
        state = MovementState.crouching;
        moveSpeed = crouchSpeed;
        sprinting = false; // 蹲伏时强制清除冲刺标记,避免误判滑铲
    }
    // 冲刺状态:地面、按冲刺键、按W前进时进入
    else if (grounded && Input.GetKey(sprintKey) && Input.GetKey(KeyCode.W))
    {
        state = MovementState.sprinting;
        moveSpeed = sprintSpeed;
        sprinting = true;
    }
    // 地面普通行走
    else if (grounded)
    {
        state = MovementState.walking;
        moveSpeed = walkSpeed;
        sprinting = false;
    }
    // 空中状态
    else
    {
        state = MovementState.air;
    }
}

然后替换原有的MyInput()方法里的蹲伏相关逻辑,删掉重复的滑铲判断:

private void MyInput()
{
    horizontalInput = Input.GetAxisRaw("Horizontal");
    verticalInput = Input.GetAxisRaw("Vertical");

    // 跳跃逻辑保持原有逻辑不变
    if (Input.GetKey(jumpKey) && readyToJump && grounded)
    {
        readyToJump = false;
        Jump();
        Invoke(nameof(ResetJump), jumpCooldown);
    }

    // 按下蹲伏键统一处理
    if (Input.GetKeyDown(crouchKey))
    {
        // 冲刺状态下按蹲伏=触发滑铲
        if (sprinting && grounded)
        {
            StartSlide();
        }
        // 非冲刺状态按蹲伏=进入普通蹲伏
        else
        {
            sliding = false;
            transform.localScale = new Vector3(transform.localScale.x, crouchYScale, transform.localScale.z);
            rb.AddForce(Vector3.down * 5f, ForceMode.Impulse);
        }
    }

    // 松开蹲伏键统一处理
    if (Input.GetKeyUp(crouchKey))
    {
        // 处于滑铲状态就停止滑铲
        if (sliding)
        {
            StopSlide();
        }
        // 普通蹲伏状态就恢复默认身高
        else
        {
            transform.localScale = new Vector3(transform.localScale.x, startYScale, transform.localScale.z);
        }
    }
}

最后打开Update()方法,删掉里面重复写的这两段滑铲/蹲伏触发代码,避免重复执行冲突:

// 删除以下两行重复逻辑
// if (Input.GetKeyDown(crouchKey) && sprinting)
//     StartSlide();
// if (Input.GetKeyUp(crouchKey) && sliding)
//     StopSlide();

改完之后测试即可:静止/走路状态按左Ctrl会进入普通蹲伏,移速为预设的crouchSpeed;冲刺状态按左Ctrl正常触发滑铲,不会再出现蹲伏移速被覆盖的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 18:09:37