实现原理
欧拉角跳变处理
Unity的欧拉角范围为0~360
,当角度跨过360°时会归零,直接计算相邻帧的差值会导致错误(如359°→1°会被误判为-358°而非+2°)。累计总旋转角度
通过跟踪每帧的角度变化量,修正跳变误差,最终累计总旋转度数,再除以360得到圈数。
完整代码
using UnityEngine;
public class RotationCounter : MonoBehaviour
{
private float _previousEulerY; // 上一帧的Y轴欧拉角
private float _totalRotation; // 累计总旋转度数
void Start()
{
// 初始记录当前欧拉角Y
_previousEulerY = transform.eulerAngles.y;
}
void Update()
{
// 获取当前欧拉角Y
float currentEulerY = transform.eulerAngles.y;
// 计算帧间角度差
float delta = currentEulerY - _previousEulerY;
// 修正360°跳变
if (delta > 180f)
{
delta -= 360f;
}
else if (delta < -180f)
{
delta += 360f;
}
// 累加总旋转度数
_totalRotation += delta;
// 更新上一帧角度
_previousEulerY = currentEulerY;
// 计算圈数(正值为顺时针,负值为逆时针)
float totalTurns = _totalRotation / 360f;
Debug.Log($"总圈数: {totalTurns:F2}");
}
}
使用说明
脚本挂载
将脚本附加到需要监测旋转的物体上。方向判断
正圈数:顺时针旋转累计
负圈数:逆时针旋转累计
精度控制
输出结果保留两位小数(F2
),若需更高精度可修改格式字符串。
关键问题处理
1. 角度跳变修正
if (delta > 180f) delta -= 360f;
else if (delta < -180f) delta += 360f;
当相邻帧角度差超过180°时,视为发生360°跳变,反向修正差值
示例:359°→1°的原始差值为-358°,修正后为+2°
2. 浮点误差处理
// 可添加阈值过滤微小抖动
if (Mathf.Abs(delta) < 0.01f) delta = 0f;
在工业级应用中建议添加,避免微小抖动影响累计值
扩展功能
1. 重置计数器
public void ResetCounter()
{
_totalRotation = 0f;
_previousEulerY = transform.eulerAngles.y;
}
调用此方法可重置累计圈数
2. 多轴旋转分离(高级)
若需精确计算绕Y轴的旋转(忽略其他轴影响),需使用投影法:
Vector3 previousForward = transform.forward;
// 假设物体绕Y轴旋转后
Vector3 currentForward = transform.forward;
// 计算XZ平面投影的夹角变化
float angleDelta = Vector3.SignedAngle(
previousForward,
currentForward,
Vector3.up
);
_totalRotation += angleDelta;
此方法通过物体朝向在水平面的投影计算纯Y轴旋转角度,避免其他轴干扰
性能优化建议
避免每帧计算
若非实时需求,可在特定事件(如碰撞时)触发计算。使用缓存机制
若物体静止时不旋转,可通过标记跳过计算:
if (Mathf.Approximately(delta, 0f)) return;
总结
核心思路:跟踪相邻帧角度变化,修正跳变误差,累计总度数
扩展应用:可用于制作转速表、解锁谜题(如旋钮转3圈触发机关)等场景
进阶方向:结合四元数差值计算更精确的轴向旋转量