类似原神的3D游戏自由攀爬系统边缘攀爬及斜墙检测问题求助
边缘攀爬系统问题修复方案
一、射线检测逻辑优化(解决斜墙失效、误判问题)
当前双射线只适配垂直墙面,斜墙时垂直向下射线路径不对,直接空射。得改这几点:
- 第二个射线别用世界空间的
Vector3.down,改成沿墙面法线的垂直向下方向投射——也就是墙面的“下”方向,这样斜墙边缘才能被检测到。 - 加个
LayerMask只检测攀爬层,避免误触地面、道具这些无关物体。 - 用角色碰撞体中心当检测起点,别用
transform.position,模型偏移会导致检测不准。
修改后的示例代码:
[SerializeField] private LayerMask climbLayer; // 拖拽攀爬层到这里 [SerializeField] private CapsuleCollider playerCollider; private bool edgeDetect() { RaycastHit firstHit; // 用碰撞体中心做检测起点,更贴合角色实际位置 Vector3 position = playerCollider.bounds.center + detectionOffcet; // 只检测指定攀爬层,排除干扰 if (Physics.Raycast(position, transform.forward, out firstHit, 2f, climbLayer)) { // 第二个射线起点:沿墙面法线向上偏移,适配斜墙的边缘高度 Vector3 secondRayStart = firstHit.point + transform.forward * playerRadius + firstHit.normal * (0.6f * playerHeight); // 第二个射线方向:沿墙面的垂直向下方向(投影掉法线的垂直分量) Vector3 secondRayDir = -Vector3.ProjectOnPlane(firstHit.normal, Vector3.up).normalized; // 拉长射线长度,适配斜墙的边缘跨度 if (Physics.Raycast(secondRayStart, secondRayDir, out var secondHit, playerHeight * 1.5f, climbLayer)) { Targetposition = secondHit.point + edgeOffcet; m_Animator.SetTrigger("edge"); // 目标位置加碰撞体中心偏移,避免角色模型悬空 Vector3 climbEnd = secondHit.point + playerCollider.center; // 调整MatchTarget的时间窗口和权重,让动画过渡更平滑 m_Animator.MatchTarget(climbEnd, Quaternion.LookRotation(-firstHit.normal), AvatarTarget.Root, new MatchTargetWeightMask(new Vector3(1, 1, 0), 0), // 只匹配位置,忽略旋转权重 0.1f, 0.8f); // 覆盖动画主要攀爬阶段,别搞太短 return true; } } return false; }
二、角色状态与动画控制(解决坠落、卡顿问题)
- 触发边缘攀爬时,立刻禁用角色重力+锁死移动输入,物理引擎的坠落力和动画驱动冲突就是卡顿的根源。可以设
rigidbody.isKinematic = true,或者关重力rigidbody.useGravity = false,动画播完再恢复。 - 别用0到0.09f这么短的MatchTarget时间窗口,动画刚启动就结束匹配,角色根本来不及到位。改成0.1f到0.8f,覆盖动画的核心攀爬动作阶段。
- 动画状态机里锁死状态:播放边缘攀爬动画时,禁止切换到坠落、移动状态,避免频繁状态跳变导致卡顿——比如给
edge状态设Exit Time为1,或者用布尔参数控制过渡。
三、斜墙适配细节
- 角色旋转别直接用
Quaternion.LookRotation(-firstHit.normal),斜墙法线不是水平的,角色会歪得离谱。先把法线投影到XZ平面再算旋转:
// 只取法线的水平分量做朝向,保证角色直立 Vector3 wallForward = -Vector3.ProjectOnPlane(firstHit.normal, Vector3.up).normalized; Quaternion targetRot = Quaternion.LookRotation(wallForward, Vector3.up);
- 动态调整
edgeOffcet,用firstHit.normal * 0.1f代替固定值,让角色始终贴紧墙面,不会穿模或悬空。
四、调试技巧
- 在Scene视图画射线,实时看检测是否准确:加
Debug.DrawRay(position, transform.forward * 2f, Color.red)和Debug.DrawRay(secondRayStart, secondRayDir * playerHeight *1.5f, Color.blue),直观看到射线的位置和方向。 - 打印
firstHit.normal和secondHit.point的值,确认斜墙场景下是否正确命中边缘。
内容的提问来源于stack exchange,提问作者Dev
相关产品推荐
相关产品推荐

