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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 13:57:53