Unity2D中IEnumerator计时失效:监控摄像头旋转无停顿问题求助
Unity2D监控摄像头旋转脚本问题
需求:让监控摄像头在0°至90°范围内可控往返旋转,两端停顿4秒。当前运行问题:旋转过快且无停顿效果,对IEnumerator的使用逻辑存在疑惑。
原脚本代码
using System.Collections; using System.Collections.Generic; using UnityEngine; public class SecurityCameraMovement : MonoBehaviour { public float turnspeed = 0.5f; private float angle; Transform camera; private bool stop = false; void Start() { camera = gameObject.GetComponent<Transform>(); } IEnumerator movement() { angle = camera.eulerAngles.z; if(angle > 90){ stop = true; yield return new WaitForSeconds(4); } if(angle < 1){ stop = false; yield return new WaitForSeconds(4); } if(angle > 0 && angle < 90 && stop == false){ transform.rotation = Quaternion.Euler(0,0, angle + turnspeed); yield return new WaitForSeconds(1); } if(stop == true){ transform.rotation = Quaternion.Euler(0,0, angle - turnspeed); yield return new WaitForSeconds(1); } } void Update() { StartCoroutine(movement()); } }
预期运动弧度示意图

问题分析与修正方案
核心问题
- Update每帧启动协程:
Update方法每帧都会调用StartCoroutine(movement()),导致同时运行成百上千个协程实例,旋转速度被叠加,停顿逻辑也被多个协程打乱,自然看不到预期效果。 - 协程逻辑不连贯:原协程是单次执行逻辑,没有循环持续控制旋转流程,且角度判断存在误差(比如
angle < 1的判断不够严谨,eulerAngles可能出现359°这类接近0的情况)。
修正后的脚本
using System.Collections; using UnityEngine; public class SecurityCameraMovement : MonoBehaviour { public float turnSpeed = 0.5f; // 每秒旋转的角度 public float pauseDuration = 4f; // 两端停顿时长 private float targetAngle; private bool rotateToMax = true; // true: 转向90°,false: 转回0° void Start() { // 初始化目标角度,从当前角度或直接设定初始方向 targetAngle = rotateToMax ? 90f : 0f; // 仅启动一次协程,持续控制旋转流程 StartCoroutine(CameraRotationLoop()); } IEnumerator CameraRotationLoop() { while (true) { // 平滑旋转至目标角度,误差小于0.1°时视为到达 while (Mathf.Abs(transform.eulerAngles.z - targetAngle) > 0.1f) { float currentAngle = transform.eulerAngles.z; // 按帧平滑移动角度,Time.deltaTime确保速度不受帧率影响 float newAngle = Mathf.MoveTowards(currentAngle, targetAngle, turnSpeed * Time.deltaTime); transform.rotation = Quaternion.Euler(0, 0, newAngle); yield return null; // 等待下一帧再更新 } // 到达端点后停顿指定时长 yield return new WaitForSeconds(pauseDuration); // 切换旋转方向和目标角度 rotateToMax = !rotateToMax; targetAngle = rotateToMax ? 90f : 0f; } } }
关键修改说明
- 单协程持续运行:仅在
Start中启动一次协程,用while(true)循环维持旋转-停顿-切换的完整流程,避免多协程冲突。 - 平滑旋转控制:使用
Mathf.MoveTowards实现稳定的平滑旋转,配合Time.deltaTime让旋转速度在不同帧率下保持一致。 - 严谨的角度判断:通过目标角度对比+误差阈值判断是否到达端点,避免eulerAngles的循环值(如359°)导致的逻辑错误。
- 清晰的状态切换:用
rotateToMax标记旋转方向,切换时直接更新目标角度,逻辑更直观。
内容的提问来源于stack exchange,提问作者sweat
相关产品推荐
相关产品推荐

