Unity 2D 适配父级旋转、带角度限制的硬点鼠标瞄准象限异常
硬点瞄准逻辑异常排查与修正
异常根因
当前逻辑的核心遗漏是所有旋转角度属于环形循环数值域,不存在绝对的线性大小比较关系。
- 原代码计算
minAngle、maxAngle时没有对结果做0~360范围的归一化,会出现大于360的计算值(比如槽位z轴旋转270°时,计算得到的maxAngle为380°) - 当允许旋转的区间跨过0°/360°的循环边界时(例如合法范围实际为340°~20°),原有的线性判断
angle < minAngle则设为minAngle会完全失效:- 此时落在合法范围内的角度(比如0°、10°这类靠近0度的鼠标瞄准值),会因为数值上小于340°的minAngle,被强制钳制到340°的边界值
- 这个失效的区间正好覆盖屏幕右上象限对应的角度范围,和实际观察到的90度区间逻辑混乱、其余270度范围运行正常的现象完全匹配
逻辑修正要点
- 统一所有角度值的计算基准,将任意范围的输入角度全部归一化到0360的环形域内,替代原有仅支持-180°180°转换的
OneEightyToThreeSixty()方法 - 提前判断当前允许的旋转区间是否跨过0°边界:当归一化后的minAngle值大于maxAngle值时,说明区间是绕0点环绕的,不能用常规的线性大小判断
- 对跨边界的区间调整合法性判断:合法角度范围为「角度 >= minAngle 或者 角度 <= maxAngle」,而非原来的「角度在min和max之间」
- 角度钳制时采用环形距离计算,判断当前瞄准角度离哪个区间边界更近,再钳制到对应值,避免直接数值大小比较带来的错误
参考修正代码片段
public void AimAtMouse() { Vector3 dir = Input.mousePosition - Camera.main.WorldToScreenPoint(transform.position); angle = Mathf.Atan2(dir.y, dir.x) * Mathf.Rad2Deg; // 计算允许的角度范围 minAngle = (transform.eulerAngles.z - 20) + 90f; maxAngle = (transform.eulerAngles.z + 20) + 90f; // 所有角度统一归一到0~360范围 angle = NormalizeAngle(angle); minAngle = NormalizeAngle(minAngle); maxAngle = NormalizeAngle(maxAngle); // 判断是否为跨0度的环绕区间 bool isWrappedRange = minAngle > maxAngle; bool isLegalAngle; if (isWrappedRange) { isLegalAngle = angle >= minAngle || angle <= maxAngle; } else { isLegalAngle = angle >= minAngle && angle <= maxAngle; } // 角度不在合法范围时,钳制到最近的边界 if (!isLegalAngle) { float distToMin = Mathf.DeltaAngle(angle, minAngle); float distToMax = Mathf.DeltaAngle(angle, maxAngle); angle = Mathf.Abs(distToMin) < Mathf.Abs(distToMax) ? minAngle : maxAngle; } hardpoint.transform.rotation = Quaternion.AngleAxis(angle, Vector3.forward); } // 全角度范围归一方法,替代原有的180-360转换逻辑 public float NormalizeAngle(float inputAngle) { inputAngle = Mathf.Repeat(inputAngle, 360f); return inputAngle < 0 ? inputAngle + 360f : inputAngle; }
补充:原
OneEightyToThreeSixty()方法仅覆盖-180°~180°输入值的转换逻辑,无法处理minAngle、maxAngle计算过程中可能出现的超360°的越界值,这也是触发异常的隐性原因。
内容的提问来源于stack exchange,提问作者Binkling
相关产品推荐
相关产品推荐

