Unity协程异常退出while循环:条件满足却终止
Unity协程while循环异常终止的原因分析
核心问题拆解
你遇到的现象本质是代码缩进误解+浮点数精度陷阱共同导致的,先逐个理清:
1. 第一个“正常运行”的代码其实是错误逻辑
你写的第一段代码存在缩进陷阱,实际执行逻辑和你想的不一样:
IEnumerator initialize_reference_att() { Quaternion zero = new Quaternion(0, 0, 0, 0); // while循环只包裹了Debug.Log一行,yield return null在循环外! while (Input.gyro.attitude == zero) Debug.Log("This line is required otherwise exits while without looping"); // 这行是循环结束后才执行一次 yield return null; reference_attitude = Input.gyro.attitude; Debug.Log("Reference attitude set to " + reference_attitude); yield return null; }
这个写法里,while是主线程死循环——它会不停打印日志,完全卡住主线程,直到陀螺仪的姿态值真的偏离零四元数才会退出循环。你觉得它“正常”,只是因为死循环高频检测到了陀螺仪数据的变化,而不是协程正确的帧间等待逻辑。
2. 第二个代码提前终止的真正原因
当你改成只保留yield return null在循环里时:
while (Input.gyro.attitude == zero) yield return null;
这时候协程才是正确的每帧暂停一次,但问题出在Quaternion的==判断不可靠:
陀螺仪的姿态值是由浮点数组成的四元数,浮点数本身存在精度误差——哪怕逻辑上是零姿态,实际存储的数值可能和你手动创建的new Quaternion(0,0,0,0)有极小的差异(比如1e-9级别的误差),直接用==比较会判定为不相等,导致循环第一帧就直接退出。
而第一个代码的死循环是高频轮询,能捕捉到陀螺仪从“绝对零”到“有微小数值”的瞬间变化,所以看起来能正常等到姿态值出现。
3. 正确的写法应该怎么做
不要直接用==比较四元数,改用近似相等判断:
IEnumerator initialize_reference_att() { Quaternion zero = Quaternion.identity; // 用角度差判断近似零姿态,阈值可根据需求调整 while (Quaternion.Angle(Input.gyro.attitude, zero) < 0.01f) { yield return null; // 确保每帧暂停,不卡主线程 } reference_attitude = Input.gyro.attitude; Debug.Log("Reference attitude set to " + reference_attitude); yield return null; }
内容的提问来源于stack exchange,提问作者Patroclos
相关产品推荐
相关产品推荐

