Unity 3D角色跳跃半空贴靠物体悬浮问题修复咨询
问题解决:Unity角色半空贴靠物体悬浮问题
问题原因
你的移动脚本中,rb.velocity = Vector3.Lerp(rb.velocity, Vector3.zero, moveSmoothing);这行代码会将**整个速度向量(包括Y轴下落速度)**向零值插值,当角色在空中贴靠物体时,碰撞会抵消Y轴方向的重力,再加上这行代码持续将Y轴速度拉至零,最终导致角色悬浮。
修复方案(不破坏现有移动逻辑)
我们只需要修改速度插值的逻辑,保留Y轴速度不受插值影响,同时添加简单地面检测优化行为:
1. 添加地面检测变量
在脚本顶部新增地面检测相关参数:
// 地面检测配置 public float groundCheckDistance = 0.1f; public LayerMask groundLayer; private bool isGrounded;
2. 实现地面检测逻辑
在FixedUpdate中添加物理层面的地面检测(物理逻辑放在FixedUpdate更稳定):
private void FixedUpdate() { // 从角色原点向下发射射线,判断是否接触地面 isGrounded = Physics.Raycast(transform.position, Vector3.down, groundCheckDistance, groundLayer); // 原有下落加速逻辑保留 if (rb.velocity.y < 0) { rb.velocity += Vector3.up * Physics.gravity.y * fallMultiplayer * Time.deltaTime; } }
3. 修改速度插值代码
将原有的全向量插值替换为仅XZ轴插值,保留Y轴下落速度:
// 仅对水平方向(XZ轴)速度进行平滑插值,不影响Y轴下落 Vector3 currentVelocity = rb.velocity; Vector3 horizontalVelocity = Vector3.Lerp(new Vector3(currentVelocity.x, 0, currentVelocity.z), Vector3.zero, moveSmoothing); rb.velocity = new Vector3(horizontalVelocity.x, currentVelocity.y, horizontalVelocity.z);
4. 可选:优化空中移动力度
如果希望空中移动比地面稍弱,可在添加移动力时根据接地状态调整:
// 移动逻辑:空中移动时降低速度(可根据需求调整比例) float currentMoveSpeed = isGrounded ? MoveSpeed : MoveSpeed * 0.7f; rb.AddForce(targetMoveDirection * currentMoveSpeed, ForceMode.VelocityChange);
完整修改后的脚本
using System.Collections; using System.Collections.Generic; using UnityEngine; public class movement : MonoBehaviour { public Rigidbody rb; public float MouseSensitivity; public float MoveSpeed; public float jumpForce; public float fallMultiplayer = 2.0f; // Smoothing factors public float moveSmoothing = 0.1f; public float rotateSmoothing = 0.1f; //animator public Animator anim; bool isJumping = false; // 地面检测配置 public float groundCheckDistance = 0.1f; public LayerMask groundLayer; private bool isGrounded; private Vector3 targetMoveDirection; private Quaternion targetRotation; void Start() { //Cursor.visible = false; } void Update() { anim.SetBool("jump",false); //Look around Quaternion rotationDelta = Quaternion.Euler(new Vector3(0, Input.GetAxis("Mouse X") * MouseSensitivity, 0)); targetRotation = rb.rotation * rotationDelta; rb.MoveRotation(Quaternion.Lerp(rb.rotation, targetRotation, rotateSmoothing)); //vertical parameter anim.SetFloat("vertical moving", Input.GetAxis("Vertical")); anim.SetFloat("horizontal", Input.GetAxis("Horizontal")); //Move targetMoveDirection = transform.forward * Input.GetAxis("Vertical") + transform.right * Input.GetAxis("Horizontal"); float currentMoveSpeed = isGrounded ? MoveSpeed : MoveSpeed * 0.7f; // 空中移动降速(可选) rb.AddForce(targetMoveDirection * currentMoveSpeed, ForceMode.VelocityChange); // 仅平滑水平速度,保留Y轴下落速度 Vector3 currentVelocity = rb.velocity; Vector3 horizontalVelocity = Vector3.Lerp(new Vector3(currentVelocity.x, 0, currentVelocity.z), Vector3.zero, moveSmoothing); rb.velocity = new Vector3(horizontalVelocity.x, currentVelocity.y, horizontalVelocity.z); //Jump if (anim.GetCurrentAnimatorStateInfo(0).IsName("Jump")) { isJumping = true; } else { isJumping = false; } if (Input.GetKeyDown(KeyCode.Space) && isGrounded && !isJumping) { anim.SetBool("jump",true); rb.AddForce(Vector3.up * jumpForce, ForceMode.VelocityChange); rb.AddForce(Physics.gravity, ForceMode.Acceleration); } } private void FixedUpdate() { // 地面检测 isGrounded = Physics.Raycast(transform.position, Vector3.down, groundCheckDistance, groundLayer); if (rb.velocity.y < 0) { rb.velocity += Vector3.up * Physics.gravity.y * fallMultiplayer * Time.deltaTime; } } }
注意事项
- 在Unity编辑器中,将
groundLayer设置为你的地面所在图层,避免误检测其他物体。 - 调整
groundCheckDistance数值,确保角色站在地面时能正确触发检测,数值略大于角色碰撞体底部到原点的偏移即可。
内容的提问来源于stack exchange,提问作者neviot
相关产品推荐
相关产品推荐

