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

Unity中相机随机翻转复位的代码优化方案咨询

相机随机翻转效果优化方案

我正在做一款游戏,需要让相机在随机时间间隔内随机翻转至倒立状态再复位,而且这个效果要在游戏全程持续。我写了下面这段测试代码,但感觉有更优的实现方式,求改进建议或者全新的优化方案。

原测试代码:

public Camera cam;
float time = 0;
private float cumulativeRotation = 0f;
private int rotationSpeed = 1;

public static int test = 0;

private int minNumber;
private int minNumber2;
private int maxNumber;
private void Start() {
    minNumber = Random.Range(5, 15);
    minNumber2 = Random.Range(16, 25);
    maxNumber = Random.Range(26, 40); 
}
int count = 0;
void Update() {
    
    time += Time.deltaTime;

    float rotationThisFrame = Mathf.Min(180f - cumulativeRotation, rotationSpeed * Time.deltaTime);

    
    if (time >= minNumber && time <= minNumber2 && test == 0) {
        cam.transform.Rotate(Vector3.forward, 180.0f * Time.deltaTime);
        cumulativeRotation += rotationThisFrame;
        if (cumulativeRotation >= 1f) {
            // We are done rotating. Stop rotating on further frames.
            cam.transform.Rotate(Vector3.back, 180.0f * Time.deltaTime);
            test = 1;
            // Reset cumulativeRotation tracker for next time.
            cumulativeRotation = 0f;

            minNumber = minNumber + minNumber2;
            Debug.Log("MIN NUMBER: " + minNumber);
            minNumber2 = minNumber2 + minNumber2;
            Debug.Log("MIN NUMBER2 : " + minNumber2);

        }
        
    }
    
    if(time >= minNumber2  && time <= maxNumber && test == 1) {
        cam.transform.Rotate(Vector3.forward, 180.0f * Time.deltaTime);
        cumulativeRotation += rotationThisFrame;
        if (cumulativeRotation >= 1f) {
            // We are done rotating. Stop rotating on further frames.
            cam.transform.Rotate(Vector3.back, 180.0f * Time.deltaTime);
            test = 0;
            // Reset cumulativeRotation tracker for next time.
            cumulativeRotation = 0f;
            maxNumber = maxNumber + maxNumber;
            Debug.Log("MaxNumber: " + maxNumber);
        }

    }
}

原代码存在的问题

  1. 状态管理不规范:用static int test做状态标记,全局静态变量容易引发跨场景、跨实例的意外问题
  2. 时间逻辑混乱:全局累加time判断间隔,游戏暂停或场景切换后会完全打乱节奏
  3. 旋转逻辑矛盾:同一帧同时执行Rotate(Vector3.forward)和Rotate(Vector3.back),等于没有旋转
  4. 翻转判断错误:cumulativeRotation >=1f的阈值完全不合理,1度远未达到180度的翻转需求
  5. 间隔逻辑不符合需求:minNumber = minNumber + minNumber2会让等待间隔指数级增长,和“随机时间间隔”的要求不符

优化方案:用协程实现循环随机翻转

协程天生适合这种分阶段的异步流程,能把「等待随机时间→翻转相机→等待随机时间→复位相机」的逻辑拆得清晰易懂,不需要在Update里堆一堆条件判断。

优化后的代码:

using UnityEngine;
using System.Collections;

public class CameraFlip : MonoBehaviour
{
    public Camera targetCam;
    // 翻转/复位的速度(单位:度/秒)
    public float rotationSpeed = 180f;
    // 两次动作之间的等待时间范围
    public float minWaitTime = 5f;
    public float maxWaitTime = 40f;

    private void Start()
    {
        // 启动全程循环的翻转协程
        StartCoroutine(FlipCameraLoop());
    }

    private IEnumerator FlipCameraLoop()
    {
        while (true) // 无限循环,游戏全程执行
        {
            // 随机等待一段时间
            float waitTime = Random.Range(minWaitTime, maxWaitTime);
            yield return new WaitForSeconds(waitTime);

            // 翻转到倒立状态(绕Z轴转180度)
            yield return RotateCameraTo(180f);

            // 随机等待后复位
            waitTime = Random.Range(minWaitTime, maxWaitTime);
            yield return new WaitForSeconds(waitTime);

            // 复位到初始角度
            yield return RotateCameraTo(0f);
        }
    }

    private IEnumerator RotateCameraTo(float targetZRotation)
    {
        float currentZ = targetCam.transform.eulerAngles.z;
        // 处理角度循环问题(比如350度到10度应该转20度而非340度)
        float targetZ = Mathf.DeltaAngle(currentZ, targetZRotation) + currentZ;

        float rotationRemaining = Mathf.Abs(targetZ - currentZ);

        // 留个小阈值避免因浮点误差导致无限循环
        while (rotationRemaining > 0.1f)
        {
            float rotateAmount = Mathf.Min(rotationSpeed * Time.deltaTime, rotationRemaining);
            // 计算旋转方向
            float direction = targetZ > currentZ ? 1f : -1f;
            targetCam.transform.Rotate(Vector3.forward, direction * rotateAmount);

            currentZ = targetCam.transform.eulerAngles.z;
            rotationRemaining = Mathf.Abs(Mathf.DeltaAngle(currentZ, targetZ));

            yield return null; // 等待下一帧
        }

        // 最后直接设置到目标角度,消除累积误差
        Vector3 finalRotation = targetCam.transform.eulerAngles;
        finalRotation.z = targetZRotation;
        targetCam.transform.eulerAngles = finalRotation;
    }
}

优化点说明

  • 协程逻辑清晰,每个步骤独立,可读性和维护性大幅提升
  • 每次等待时间都是随机生成,完全符合“随机时间间隔”的需求
  • 旋转方法处理了角度循环问题,保证走最短路径旋转,且最终角度精准
  • 所有参数都暴露在Inspector面板,无需改代码就能调试速度、等待时间等
  • 没有使用全局静态变量,状态管理更安全

内容的提问来源于stack exchange,提问作者Nautic52

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 14:12:49