实现车辆旋转复位功能时Quaternion.Lerp函数触发断言错误求助
车辆旋转控制系统的Quaternion.Lerp断言错误修复
问题描述
开发车辆旋转控制系统时,需求为:按住空格键,车辆逐步旋转至90度并保持姿态;松开空格键,车辆逐步恢复至0度旋转。但运行时触发断言错误:Assertion failed on expression: '!CompareApproximately(aScalar, 0.0F)'
错误原因分析
- 成员变量初始化错误:
Start方法中重新声明了局部变量endRot,导致类成员endRot始终为默认的Quaternion.identity(即0度旋转)。此时Quaternion.Lerp的两个插值参数完全相同,当lerpTimer趋近于0时,Unity内部的插值断言触发错误。 - 插值边界未处理:即使插值参数正常,当
lerpTimer无限接近0时,也可能触发Unity的内部参数检查断言。
修复方案
- 修正
endRot的赋值逻辑,确保类成员变量被正确初始化,而非创建局部变量覆盖。 - 添加边界值判断,跳过不必要的插值操作,直接设置目标旋转值。
修正后的完整代码
using System.Collections; using System.Collections.Generic; using UnityEngine; public class Movement : MonoBehaviour { private static float turnTimer = 2f; private float turnTimeElapsed; private float clampedTimeElapsed; private float lerpTimer; [SerializeField] private float turnSpeed; Quaternion endRot; Rigidbody ridgy; private void Start() { ridgy = GetComponent<Rigidbody>(); turnTimeElapsed = 0f; // 直接给类成员变量赋值,避免局部变量覆盖 endRot = Quaternion.Euler(0f, 90f, 0f); } private void Update() { if (Input.GetKey(KeyCode.Space) && turnTimeElapsed < turnTimer) { turnTimeElapsed += turnSpeed * Time.deltaTime; } else if (!Input.GetKey(KeyCode.Space) && turnTimeElapsed > 0) { turnTimeElapsed -= turnSpeed * Time.deltaTime; } clampedTimeElapsed = Mathf.Clamp(turnTimeElapsed, 0f, turnTimer); lerpTimer = clampedTimeElapsed / turnTimer; // 边界值判断,直接设置旋转避免触发断言 if (Mathf.Approximately(lerpTimer, 0f)) { transform.rotation = Quaternion.identity; } else if (Mathf.Approximately(lerpTimer, 1f)) { transform.rotation = endRot; } else { transform.rotation = Quaternion.Lerp(Quaternion.identity, endRot, lerpTimer); } } }
额外优化提示
- 若使用
Rigidbody控制物理对象,建议在FixedUpdate中修改ridgy.rotation,而非直接操作transform.rotation,避免物理引擎与直接变换的冲突。 turnSpeed数值需根据实际场景调整,确保旋转过程平滑自然。
内容的提问来源于stack exchange,提问作者Incoherent Thoughts
相关产品推荐
相关产品推荐

