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

ThreeJS FPS角色WASD移动:松开按键后立即停止移动而非滑行的实现方法

ThreeJS FPS角色WASD移动:松开按键后立即停止移动而非滑行的实现方法

兄弟我太懂你说的那种冰面滑行的糟心感了——本来想精准停住结果滑出去老远,完全破坏FPS的操作爽感。咱们直接对着代码改,分分钟解决这个问题:

问题根源

你现在的代码里,松开按键后playerVelocity还保留着之前的水平移动速度,然后通过addScaledVector的阻尼参数慢慢减速,所以才会出现夸张的滑行。要实现“松键即停”,核心就是在没有移动输入时,直接清空水平方向的速度,同时保留Y轴的速度阻尼(毕竟跳跃、下落的物理效果不能丢)。

具体修改方案

找到你更新循环里的这段代码:

this.playerVelocity.addScaledVector(this.playerVelocity, damping) // damping is for jumping
const deltaPosition = this.playerVelocity.clone().multiplyScalar(deltaTime)
this.bounds.translate(deltaPosition)
this.camera.position.copy(this.bounds.end)

把它改成下面这样:

// 先判断是否有任何WASD移动输入
const hasMovementInput = this.keyStates['KeyW'] || this.keyStates['KeyA'] || this.keyStates['KeyS'] || this.keyStates['KeyD'];

if (!hasMovementInput) {
  // 无输入时:清空水平方向(X、Z轴)速度,仅保留Y轴速度用于跳跃阻尼
  this.playerVelocity.x = 0;
  this.playerVelocity.z = 0;
} else {
  // 有输入时:正常应用阻尼(如果想要更干脆的移动,也可以删掉这行)
  this.playerVelocity.addScaledVector(this.playerVelocity, damping);
}

// 后面的位置更新逻辑保持不变
const deltaPosition = this.playerVelocity.clone().multiplyScalar(deltaTime)
this.bounds.translate(deltaPosition)
this.camera.position.copy(this.bounds.end)

额外调整(可选)

如果你还是想要一丢丢极其轻微的减速缓动(完全不会像冰面那样滑),可以把上面的this.playerVelocity.x = 0和this.playerVelocity.z = 0改成强阻尼的方式:

if (!hasMovementInput) {
  // 给水平速度施加极强阻尼,几帧内就会减速到0
  this.playerVelocity.x *= 0.1;
  this.playerVelocity.z *= 0.1;
}

这样修改后,角色松开移动按键就会立刻(或极快)停住,完全不会有过度滑行的问题,同时也不影响跳跃和下落的正常物理效果。

备注:内容来源于stack exchange,提问作者Miger

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.14 08:24:31