Unity中敌人剑高速旋转时如何准确检测180度弧完成状态?
解决Unity中剑180度旋转的完成检测问题
你的核心问题出在欧拉角逻辑错误和旋转控制不严谨上,以下是具体问题拆解和可行解决方案:
原代码的致命问题
transform.eulerAngles.z的取值范围是0°到360°,不存在负数,所以>= -47的判断完全无效,这是检测逻辑失效的根源。- 旋转速度控制混乱:原代码里
-1 * Time.deltaTime的旋转速度极慢,但你提到速度过快,说明实际调整了数值,大速度会导致帧间角度跳变,直接错过判断阈值。 - 用字符串名称停止协程的方式不严谨,容易出现冲突。
方案一:累计旋转角度(最直接可靠)
直接跟踪旋转的总角度,完全避开欧拉角的环绕问题:
public GameObject pivotPoint; public SpriteRenderer renderer; public float rotateSpeed = 90f; // 每秒转90度,2秒完成180度 private Coroutine rotateCoroutine; void Start() { rotateCoroutine = StartCoroutine(RotateSword()); } IEnumerator RotateSword() { renderer.enabled = true; yield return new WaitForSeconds(2); float totalRotated = 0f; float targetRotation = 180f; // 目标旋转总角度 Vector3 rotationAxis = Vector3.forward; while (totalRotated < targetRotation) { // 计算本次帧可旋转的角度,避免超过目标值 float rotateAmount = rotateSpeed * Time.deltaTime; if (totalRotated + rotateAmount > targetRotation) { rotateAmount = targetRotation - totalRotated; } transform.RotateAround(pivotPoint.transform.position, rotationAxis, -rotateAmount); totalRotated += rotateAmount; yield return null; } // 旋转完成,执行收尾 renderer.enabled = false; rotateCoroutine = null; }
方案二:修正欧拉角判断逻辑
如果一定要用欧拉角,先统一角度范围再做判断:
public GameObject pivotPoint; public SpriteRenderer renderer; public float rotateSpeed = 90f; private Coroutine rotateCoroutine; private float startAngle; private float targetAngle; void Start() { rotateCoroutine = StartCoroutine(RotateSword()); } IEnumerator RotateSword() { renderer.enabled = true; yield return new WaitForSeconds(2); // 记录初始角度(归一到0-360范围) startAngle = NormalizeAngle(transform.eulerAngles.z); // 计算顺时针转180度后的目标角度 targetAngle = NormalizeAngle(startAngle - 180f); while (true) { transform.RotateAround(pivotPoint.transform.position, Vector3.forward, -rotateSpeed * Time.deltaTime); float currentAngle = NormalizeAngle(transform.eulerAngles.z); // 判断是否到达目标角度(允许0.5度误差) if (IsAngleReached(currentAngle, targetAngle)) { // 修正到精确角度 Vector3 targetEuler = transform.eulerAngles; targetEuler.z = targetAngle; transform.eulerAngles = targetEuler; renderer.enabled = false; rotateCoroutine = null; yield break; } yield return null; } } // 将角度归一到0-360范围 float NormalizeAngle(float angle) { angle %= 360f; if (angle < 0f) angle += 360f; return angle; } // 判断当前角度是否到达目标(处理350°到10°这类环绕情况) bool IsAngleReached(float current, float target) { float angleDiff = Mathf.Abs(current - target); angleDiff = Mathf.Min(angleDiff, 360f - angleDiff); return angleDiff < 0.5f; }
方案三:Quaternion插值(平滑旋转首选)
追求更丝滑的旋转效果时,用四元数插值直接控制旋转终点:
public GameObject pivotPoint; public SpriteRenderer renderer; public float rotateSpeed = 90f; private Coroutine rotateCoroutine; void Start() { rotateCoroutine = StartCoroutine(RotateSword()); } IEnumerator RotateSword() { renderer.enabled = true; yield return new WaitForSeconds(2); // 记录初始状态 Quaternion startRot = transform.rotation; Vector3 startOffset = transform.position - pivotPoint.transform.position; // 计算目标旋转(顺时针转180度) Quaternion targetRot = startRot * Quaternion.Euler(0, 0, -180f); float rotateDuration = 180f / rotateSpeed; float elapsedTime = 0f; while (elapsedTime < rotateDuration) { elapsedTime += Time.deltaTime; float t = Mathf.Clamp01(elapsedTime / rotateDuration); // 平滑插值旋转和位置 transform.rotation = Quaternion.Lerp(startRot, targetRot, t); transform.position = pivotPoint.transform.position + targetRot * startOffset; yield return null; } // 强制修正到目标状态 transform.rotation = targetRot; transform.position = pivotPoint.transform.position + targetRot * startOffset; renderer.enabled = false; rotateCoroutine = null; }
内容的提问来源于stack exchange,提问作者LongLongMan
相关产品推荐
相关产品推荐

