You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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());

    }
}

预期运动弧度示意图

监控摄像头预期旋转范围

问题分析与修正方案

核心问题

  1. Update每帧启动协程:Update方法每帧都会调用StartCoroutine(movement()),导致同时运行成百上千个协程实例,旋转速度被叠加,停顿逻辑也被多个协程打乱,自然看不到预期效果。
  2. 协程逻辑不连贯:原协程是单次执行逻辑,没有循环持续控制旋转流程,且角度判断存在误差(比如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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 07:30:53