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

Unity Rigidbody角色爬梯时重力未禁用问题排查求助

Unity Rigidbody角色爬梯重力禁用失效问题排查与修复

你的爬梯重力禁用失效,核心问题出在OnLadder()方法的射线检测逻辑上——它依赖玩家输入的moveDirection作为射线方向,但当玩家站在梯子上没有输入移动方向时,moveDirection是零向量,Physics.Raycast会直接返回false,导致OnLadder()判断失败,最终rb.useGravity被重新设为true。

修复方案

1. 重构OnLadder()检测逻辑

放弃依赖玩家输入的方向,改用多方向射线(前后左右+上下)检测,确保即使无输入也能识别到梯子:

private bool OnLadder()
{
    float avoidFloorDistance = .1f;
    float ladderGrabDistance = .6f;
    // 向前后左右、上下发射射线,覆盖梯子可能存在的所有方向
    Vector3[] checkDirections = new Vector3[] 
    { 
        orientation.forward, orientation.back, 
        orientation.right, orientation.left,
        Vector3.up, Vector3.down
    };
    
    foreach (var dir in checkDirections)
    {
        if (Physics.Raycast(transform.position + Vector3.up * avoidFloorDistance, dir, out RaycastHit raycastHit, ladderGrabDistance))
        {
            if (raycastHit.transform.TryGetComponent(out Ladder ladder))
            {
                return true;
            }
        }
    }
    return false;
}

2. 调整MovePlayer()逻辑顺序

将重力设置提前,并在爬梯逻辑中直接跳过后续地面/空中移动代码,避免设置被覆盖:

private void MovePlayer()
{
    // 先初始化重力状态
    rb.useGravity = !(OnLadder() || OnSlope());

    // 计算移动方向
    moveDirection = orientation.forward * verticalInput + orientation.right * horizontalInput;

    if (OnLadder())
    {
        Debug.Log("Player is on the ladder.");
        // 禁用水平移动,保留垂直爬梯方向
        moveDirection.x = 0f;
        moveDirection.z = 0f; 
        moveDirection.y = verticalInput * moveSpeed; 

        rb.MovePosition(rb.position + moveDirection * Time.deltaTime);
        // 双重保障:强制禁用重力
        rb.useGravity = false;
        // 跳过后续地面/空中移动逻辑,避免干扰
        return;
    }

    // 斜坡处理
    if (OnSlope() && !exitingSlope)
    {
        rb.AddForce(GetSlopeMoveDirection() * moveSpeed * 0.35f, ForceMode.Impulse);

        if (rb.linearVelocity.y > 0)
        {
            rb.AddForce(Vector3.down * 80f, ForceMode.Force);
        }
    }

    // 地面移动
    if (grounded)
    {
        rb.AddForce(moveDirection.normalized * moveSpeed * 10f, ForceMode.Force);
    }

    // 空中移动
    else if (!grounded)
    {
        rb.AddForce(moveDirection.normalized * moveSpeed * 10f * airMultiplier, ForceMode.Force);
    }
}

额外优化建议

  • 可以给梯子添加专属的LayerMask,在OnLadder()的射线检测中指定只检测该层,减少误判概率。
  • 若爬梯时需要更平滑的移动,可将rb.MovePosition替换为rb.velocity控制,配合Mathf.Clamp限制垂直速度。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 14:25:18