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

如何让持管道的Rigidbody 3D角色遇障碍物卡顿时停止移动?

解决角色携带管道被卡时停止移动的问题

方案一:利用管道碰撞事件触发停止

  • 给管道保留Collider组件(取消Is Trigger勾选,保持常规碰撞),在Layer Collision Matrix中确保管道与障碍物的碰撞层处于可交互状态
  • 若将管道设为角色子物体,给管道添加Rigidbody并设置为Kinematic(保留碰撞检测但不受物理引擎推动)
  • 在管道挂载脚本,监听OnCollisionStay事件:当检测到与障碍物碰撞时,调用角色脚本的停止移动方法;监听OnCollisionExit事件恢复移动权限
  • 角色脚本实现停止逻辑:直接将x、z轴速度设为0,同时暂时禁用移动输入

方案二:预判碰撞阻断移动

  • 不将管道设为子物体,用FixedJoint连接角色与管道,保留管道自身物理特性
  • 在角色移动脚本中,每帧预判管道移动后的位置:用Physics.OverlapBox检测该位置是否与障碍物重叠,若重叠则停止角色移动
  • 示例代码(C#):
public Rigidbody playerRb;
public Transform pipeTransform;
public Vector3 pipeExtents; // 管道包围盒尺寸
public LayerMask obstacleLayer;
public float moveSpeed;

void FixedUpdate()
{
    float moveX = Input.GetAxis("Horizontal");
    float moveZ = Input.GetAxis("Vertical");
    Vector3 moveDir = new Vector3(moveX, 0, moveZ).normalized;

    // 计算管道移动后的预判位置
    Vector3 predictedPipePos = pipeTransform.position + moveDir * Time.fixedDeltaTime * moveSpeed;
    // 检测预判位置是否有障碍物
    Collider[] hits = Physics.OverlapBox(predictedPipePos, pipeExtents / 2, pipeTransform.rotation, obstacleLayer);

    if (hits.Length == 0)
    {
        playerRb.velocity = new Vector3(moveX * moveSpeed, playerRb.velocity.y, moveZ * moveSpeed);
    }
    else
    {
        playerRb.velocity = new Vector3(0, playerRb.velocity.y, 0);
    }
}

方案三:调整子物体碰撞设置(强制设为子物体时)

  • 若必须将管道设为角色子物体,确保管道Collider未被设置为Ignore Collision,同时角色Rigidbody勾选Use Gravity与Interpolate
  • 在角色脚本中,每帧检查管道Collider的contacts数组:若接触点数量大于0,立即停止角色移动

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 03:15:18