网格地牢爬行游戏旋转后transform.forward轴异常致移动受阻求助
问题根源
你调用CanMove时传入的是世界空间方向(Vector3.forward等),但实际移动用的是玩家本地空间方向(transform.forward)。玩家旋转后,本地方向与世界方向不再一致,导致碰撞检测的方向和实际要移动的方向不匹配——比如玩家转向X轴方向后,CanMove仍在检测Z轴方向的碰撞,错误阻止了本应允许的移动。
修复步骤
1. 统一移动与碰撞检测的方向
修改所有Move方法中CanMove的传入参数,用玩家本地空间方向替代世界空间方向:
public void MoveForward() { if (CanMove(transform.forward)) { if (AtRest) targetGridPos += transform.forward; } } public void MoveBackward() { if (CanMove(-transform.forward)) { if (AtRest) targetGridPos -= transform.forward; } } public void MoveLeft() { if (CanMove(-transform.right)) { if (AtRest) targetGridPos -= transform.right; } } public void MoveRight() { if (CanMove(transform.right)) { if (AtRest) targetGridPos += transform.right; } }
2. 优化CanMove的方向判断逻辑
原逻辑通过判断direction.z或x选择射线原点,但旋转后方向分量可能同时不为0,改用分量绝对值大小判断主移动轴向:
bool CanMove(Vector3 direction) { direction = direction.normalized; if (Mathf.Abs(direction.z) > Mathf.Abs(direction.x)) { if (Physics.Raycast(zAxisOriginA, direction, rayLength)) return false; if (Physics.Raycast(zAxisOriginB, direction, rayLength)) return false; } else { if (Physics.Raycast(xAxisOriginA, direction, rayLength)) return false; if (Physics.Raycast(xAxisOriginB, direction, rayLength)) return false; } return true; }
3. 修复旋转到位判断的精度问题
原AtRest用Vector3.Distance比较欧拉角,会因欧拉角环绕特性(如359°和1°)误判,改用四元数角度差判断:
bool AtRest { get { bool positionAtRest = Vector3.Distance(transform.position, targetGridPos) < 0.05f; Quaternion currentRot = Quaternion.Euler(transform.eulerAngles); Quaternion targetRot = Quaternion.Euler(targetRotation); bool rotationAtRest = Quaternion.Angle(currentRot, targetRot) < 0.5f; return positionAtRest && rotationAtRest; } }
额外建议
- 网格移动建议用整数网格坐标(如
Vector2Int),避免浮点精度问题,再转换为世界空间位置。 - 旋转时直接操作欧拉角Y轴更直观,比如
targetRotation = new Vector3(0, targetRotation.y ±90, 0),避免向量运算的混淆。
内容的提问来源于stack exchange,提问作者Nush
相关产品推荐
相关产品推荐

