Unity:角色防悬崖掉落的平滑移动实现方案技术问询
角色边缘平滑防掉落实现方案
核心思路
放弃直接停止移动的粗暴逻辑,通过左右两侧的地面射线检测判断悬崖位置,将玩家的输入方向投影到安全的地面区域,实现沿边缘的平滑滑动。
具体实现步骤
1. 优化射线检测逻辑
从角色胶囊体的左右两侧(稍向前偏移,避免检测自身脚下)向下发射射线,判断两侧是否存在悬崖:
// 射线配置参数,可根据角色尺寸调整 float rayLength = 2f; LayerMask groundLayer = LayerMask.GetMask("Ground"); // 替换为你的地面层 Vector3 capsuleCenter = charController.bounds.center; float sideOffset = charController.radius + 0.1f; // 射线起点超出胶囊体,避免被自身遮挡 float forwardOffset = 0.5f; // 射线向前偏移,提前检测前方边缘 // 左侧射线检测 Vector3 leftRayOrigin = capsuleCenter + (-transform.right * sideOffset) + (transform.forward * forwardOffset); bool facingDropLeft = !Physics.Raycast(leftRayOrigin, Vector3.down, rayLength, groundLayer); // 右侧射线检测 Vector3 rightRayOrigin = capsuleCenter + (transform.right * sideOffset) + (transform.forward * forwardOffset); bool facingDropRight = !Physics.Raycast(rightRayOrigin, Vector3.down, rayLength, groundLayer); // 调试可视化(可选) Debug.DrawRay(leftRayOrigin, Vector3.down * rayLength, facingDropLeft ? Color.red : Color.green); Debug.DrawRay(rightRayOrigin, Vector3.down * rayLength, facingDropRight ? Color.red : Color.green);
可选优化:用
Physics.SphereCast替代Raycast,适配角色胶囊体的碰撞范围,减少小台阶或凸起导致的误判。
2. 平滑调整移动方向
不再直接清零速度,而是根据悬崖位置截断输入方向中危险的分量,保留沿边缘的合法移动:
velocityXZ = inputDir * playerSpeed; // 左侧无地面:移除向左的移动分量 if (facingDropLeft && !facingDropRight) { float leftMovementAmount = Vector3.Dot(velocityXZ, -transform.right); if (leftMovementAmount > 0) { velocityXZ -= (-transform.right) * leftMovementAmount; } } // 右侧无地面:移除向右的移动分量 else if (facingDropRight && !facingDropLeft) { float rightMovementAmount = Vector3.Dot(velocityXZ, transform.right); if (rightMovementAmount > 0) { velocityXZ -= transform.right * rightMovementAmount; } } // 两侧均无地面:完全停止水平移动(避免掉落) else if (facingDropLeft && facingDropRight) { velocityXZ = Vector3.zero; } // 后续逻辑保持不变 velocity = new Vector3(velocityXZ.x, velocity.y, velocityXZ.z); // handle gravity charController.Move(velocity * Time.deltaTime);
3. 额外优化建议
- 添加平滑过渡:用
Vector3.Lerp将调整后的速度与原速度做插值,避免方向突变:velocityXZ = Vector3.Lerp(velocityXZ, adjustedVelocityXZ, Time.deltaTime * 8f); - 动态调整射线偏移:根据角色移动速度修改
forwardOffset,速度越快偏移越大,提前预判边缘。
内容的提问来源于stack exchange,提问作者user1022585
相关产品推荐
相关产品推荐

