Unity第三人称角色遇地形/墙体碰撞卡顿:无法侧向移动
Unity第三人称角色物理交互问题排查与修复
问题描述
我在Unity中开发第三人称角色,采用Rigidbody+Capsule Collider实现物理交互,移动与动画整体运行正常,但遇到两个核心问题:
- 台阶/地形高差:角色接触台阶或地形高度差时,无法跳跃越过障碍,直接卡在障碍底部
- 墙体/障碍物:角色碰撞墙体或其他障碍物后,无法进行左右侧向移动,仅能向后移动,机动性严重受限
已尝试调整物理材质摩擦力、修改Rigidbody参数、调整移动脚本等方案,均未解决问题。当前使用的部分移动脚本如下:
private void Update() { if(gameInput.isJumping() && isGrounded) { Jumping(); isGrounded = false; } else { isGrounded = true; } } private void FixedUpdate() { Vector2 inputVector = gameInput.GetMovementVectorNormalized(); bool isSprinting = gameInput.isSprinting(); Vector2 scaledInputVector = ScaleInputVector(inputVector, isSprinting); animator.SetFloat("horizontal", scaledInputVector.x); animator.SetFloat("vertical", scaledInputVector.y); Vector3 targetVelocity = new Vector3(scaledInputVector.x, 0, scaledInputVector.y); if(isSprinting) { addForceToRigidbody(sprint, targetVelocity); } else { addForceToRigidbody(walk, targetVelocity); } } private Vector2 ScaleInputVector(Vector2 inputVector, bool isSprinting) { if(!isSprinting) { inputVector.x = Mathf.Clamp(inputVector.x, -0.5f, 0.5f); inputVector.y = Mathf.Clamp(inputVector.y, -0.5f, 0.5f); } return inputVector; } private void addForceToRigidbody(float speed, Vector3 targetVelocity) { targetVelocity = transform.TransformDirection(targetVelocity) * speed; Vector3 velocity = rb.velocity; Vector3 velocityChange = (targetVelocity - velocity); velocityChange.x = Mathf.Clamp(velocityChange.x, -maxVelocityChange, maxVelocityChange); velocityChange.z = Mathf.Clamp(velocityChange.z, -maxVelocityChange, maxVelocityChange); velocityChange.y = 0; rb.AddForce(velocityChange, ForceMode.VelocityChange); } private bool canJump() { bool canJump = Physics.Raycast(transform.position, Vector3.down, 1.5f); return canJump; } private void Jumping() { rb.AddForce(0f, jump, 0f, ForceMode.Impulse); }
问题修复方案
1. 台阶/地形高差跳不过问题
- 修复接地检测逻辑:当前
Update中isGrounded的赋值逻辑完全错误,应使用canJump()的射线检测结果实时判断是否接地:private void Update() { isGrounded = canJump(); // 用射线检测实时更新接地状态 if(gameInput.isJumping() && isGrounded) { Jumping(); } } - 调整跳跃参数:检查
jump冲量值,第三人称角色通常需要8-12的数值(根据Rigidbody质量微调),确保力度足够越过常规台阶。 - 优化碰撞体与刚体设置:将Capsule Collider底部调整至略低于角色模型脚部,避免射线检测误判;开启Rigidbody的
Interpolate选项,提升移动平滑度,减少碰撞卡顿。 - 添加台阶辅助逻辑:在
FixedUpdate中加入胶囊体检测,当检测到前方低矮障碍时,给角色施加微小向上力辅助爬坡:// 放在FixedUpdate内 CapsuleCollider col = GetComponent<CapsuleCollider>(); float stepCheckDistance = 0.3f; float stepUpForce = 2f; if(Physics.CapsuleCast(col.bounds.center, col.bounds.center + Vector3.up * col.height, col.radius, transform.forward, stepCheckDistance)) { rb.AddForce(Vector3.up * stepUpForce, ForceMode.Impulse); }
2. 撞墙后无法侧向移动问题
- 修正移动力投影逻辑:当前移动力直接按角色朝向施加,撞墙后会被物理引擎完全抵消。修改
addForceToRigidbody,将目标速度投影到碰撞平面上:private void addForceToRigidbody(float speed, Vector3 targetVelocity) { targetVelocity = transform.TransformDirection(targetVelocity) * speed; // 获取接触面法线,将速度投影到水平平面 RaycastHit hit; Vector3 groundNormal = Vector3.up; if(Physics.Raycast(transform.position, Vector3.down, out hit, 2f)) { groundNormal = hit.normal; } targetVelocity = Vector3.ProjectOnPlane(targetVelocity, groundNormal); Vector3 velocity = rb.velocity; Vector3 velocityChange = (targetVelocity - new Vector3(velocity.x, 0, velocity.z)); velocityChange.x = Mathf.Clamp(velocityChange.x, -maxVelocityChange, maxVelocityChange); velocityChange.z = Mathf.Clamp(velocityChange.z, -maxVelocityChange, maxVelocityChange); velocityChange.y = 0; rb.AddForce(velocityChange, ForceMode.VelocityChange); } - 调整Rigidbody参数:关闭除
Freeze Rotation X/Y/Z外的所有冻结选项;将Drag设为0.5-1,避免速度骤降;Angular Drag设为5左右,防止角色旋转过度。 - 优化物理材质:给角色和障碍物的碰撞体使用低摩擦力(0.1-0.3)的物理材质,减少侧向移动时的阻力。
内容的提问来源于stack exchange,提问作者Ahmad Elmir
相关产品推荐
相关产品推荐

