You need to enable JavaScript to run this app. Unity角色水平轴输入检测失效,松开按键无法停止滑动如何解决
优惠活动
大模型
产品
解决方案
定价
更多

Unity角色水平轴输入检测失效,松开按键无法停止滑动如何解决

问题根因

  1. isMoving判断逻辑被覆盖:先判断水平轴输入修改isMoving后,紧接着的垂直轴输入判断会直接覆盖isMoving的值。这就是垂直轴逻辑正常、水平轴完全无效的核心原因:当你只按水平方向按键时,垂直轴为0,判断完水平轴把isMoving设为true后,马上被垂直轴的判断改成false。
  2. 输入获取和判断的时机错误:horizontal和vertical变量是在FixedUpdate的MovePlayer方法里才更新的,但是你在Update的CheckInput方法里提前判断这两个变量的值,拿到的都是上一轮的旧值,判断结果自然不准确。
  3. Input.GetAxis有平滑过渡:Unity默认的Input.GetAxis会对输入做平滑插值,松开按键后值不会立刻归零,会有渐变过程,就算逻辑修复也会残留一点滑行效果。

修复方案

  1. 修正isMoving的判断逻辑,合并水平、垂直轴的判断条件,避免分开判断互相覆盖值
  2. 把horizontal和vertical的输入获取移到CheckInput里,保证判断的是当前最新的输入值
  3. 把Input.GetAxis替换成Input.GetAxisRaw,松开按键输入值立刻归零
  4. 无关优化:把缩放值的初始化放到Start里,不要每帧重复赋值

修正后的完整代码

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

public class Player : MonoBehaviour
{
    [Header("Player Values")]
    [SerializeField] private float playerSpeed = 50f;
    [SerializeField] private float jumpHeight = 7f;

    [Header("Ground Check")]
    [SerializeField] private Transform groundCheck;
    [SerializeField] private LayerMask ground;
    private float checkLenght = 0.1f;

    private Rigidbody rb;
    private float horizontal;
    private float vertical;

    // Crouch Scales
    private Vector3 initialScale;
    private Vector3 crouchScale;

    // Counter Movement
    private bool isMoving;
    private bool isOnGround;
    private float counterDrag = 10f;

    private void Start()
    {
        rb = GetComponent<Rigidbody>();
        // 缩放只需要初始化一次即可
        initialScale = new Vector3(1f, 1f, 1f);
        crouchScale = new Vector3(1f, 0.5f, 1f);
    }
    void FixedUpdate()
    {
        // Player Movement
        MovePlayer();

        // Counter Movement
        ApplyCounterMovement();

        // Check Ground
        isOnGround = Physics.CheckSphere(groundCheck.position, checkLenght, ground);
    }

    private void Update()
    {
        CheckInput();
    }
    private void MovePlayer()
    {
        Vector3 movement = transform.forward * vertical * playerSpeed + transform.right * horizontal * playerSpeed;
        rb.AddForce(movement, ForceMode.Acceleration);
    }

    private void CheckInput()
    {
        if(Input.GetKeyDown(KeyCode.LeftShift))
        {
            getDown();
        }
        if(Input.GetKeyUp(KeyCode.LeftShift))
        {
            getUp();
        }

        // 直接获取最新输入,用GetAxisRaw无平滑过渡,松开立刻归零
        horizontal = Input.GetAxisRaw("Horizontal");
        vertical = Input.GetAxisRaw("Vertical");

        // 合并判断逻辑,只要水平或垂直有输入就设为正在移动,不会互相覆盖
        isMoving = Mathf.Abs(horizontal) > 0f || Mathf.Abs(vertical) > 0f;

        // Check Jump
        if(Input.GetKeyDown(KeyCode.Space))
        {
            Jump();
        }
    }

    // Crouch
    private void getDown()
    {
        transform.localScale = crouchScale;
        transform.position = new Vector3(transform.position.x, transform.position.y - 0.5f, transform.position.z);
    }

    // Get Up From Crouching
    private void getUp()
    {
        transform.localScale = initialScale;
        transform.position = new Vector3(transform.position.x, transform.position.y + 0.5f, transform.position.z);
    }

    // Apply Counter Movement
    private void ApplyCounterMovement()
    {
        rb.drag = isMoving ? 0f : counterDrag;
    }

    private void Jump()
    {
        if(isOnGround)
        {
            rb.AddForce(Vector3.up * jumpHeight, ForceMode.VelocityChange);
        }
    }
}

额外优化建议

如果还是觉得停止不够快,可以在isMoving为false的时候,直接把Rigidbody的水平速度归零,停止效果更干脆:

private void ApplyCounterMovement()
{
    if(isMoving)
    {
        rb.drag = 0f;
        return;
    }
    rb.drag = counterDrag;
    // 直接清空水平方向速度,立刻停止
    Vector3 horizontalVelocity = new Vector3(rb.velocity.x, 0f, rb.velocity.z);
    rb.velocity -= horizontalVelocity;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.11 18:00:00