Unity相机旋转优化:实现达最大转速后平滑换向并减速至停止
Unity相机旋转平滑切换方向并减速至0的修复方案
问题描述
现有BallManager脚本中,相机达到maxRotationSpeed后,当前逻辑会导致转速减速到0后变为负值,进而反向旋转且转速不断递增,不符合达到最大转速后平滑切换旋转方向并缓慢减速至0的需求。
修复后的完整代码
using System.Collections; using TMPro; using UnityEngine; public class BallManager : MonoBehaviour { public GameObject ballPrefab; public int numberOfBalls = 10; public float fallSpeed = 5; public float spawningSpeed = 1; public float ballSize = 1f; public bool randomSize = false; public TextMeshProUGUI ballCountText; // Reference to the TextMeshPro Text public float maxRotationSpeed = 180.0f; public float rotationSpeed = 10.0f; // Initial rotation speed (when it starts) public float timeToReachMaxSpeed = 30.0f; // Time in seconds to reach maximum rotation speed public float timeToDecelerate = 10.0f; // 控制从最大转速减速到0的时长 public float currentRotationSpeed; // Variable to display the current rotation speed in the inspector private int ballCount; // Counter for the number of balls private Transform cameraTransform; private int rotationDirection = 1; // 1为正方向旋转,-1为反方向旋转 private void Start() { cameraTransform = Camera.main.transform; currentRotationSpeed = rotationSpeed; // Initialize currentRotationSpeed StartCoroutine(SpawnBalls()); StartCoroutine(StartCameraRotation()); } private IEnumerator SpawnBalls() { for (int i = 0; i < numberOfBalls; i++) { GameObject ball = Instantiate(ballPrefab, transform.position, Quaternion.identity); if (randomSize) { float randomScale = Random.Range(0.5f, 2.0f); // Random size between 0.5 and 2 ball.transform.localScale = new Vector3(randomScale, randomScale, randomScale); } else { ball.transform.localScale = new Vector3(ballSize, ballSize, ballSize); } Rigidbody rb = ball.GetComponent<Rigidbody>(); rb.velocity = Vector3.down * fallSpeed; // Randomize bouncing direction Vector3 randomDirection = new Vector3(Random.Range(-1f, 1f), 0, Random.Range(-1f, 1f)).normalized; rb.AddForce(randomDirection * 5f, ForceMode.Impulse); // Increase the ball count and update the TextMeshPro Text ballCount++; ballCountText.text = "Balls: " + ballCount; yield return new WaitForSeconds(spawningSpeed); // Time delay between spawning balls } } private IEnumerator StartCameraRotation() { float timer = 0.0f; // 阶段1:从初始转速平滑加速到最大转速 while (timer < timeToReachMaxSpeed) { timer += Time.deltaTime; currentRotationSpeed = Mathf.Lerp(rotationSpeed, maxRotationSpeed, timer / timeToReachMaxSpeed); cameraTransform.RotateAround(transform.position, Vector3.up, currentRotationSpeed * rotationDirection * Time.deltaTime); yield return null; } // 阶段2:切换旋转方向并平滑减速至0 timer = 0.0f; rotationDirection *= -1; // 立即切换旋转方向 while (timer < timeToDecelerate) { timer += Time.deltaTime; // 从最大转速线性插值到0,保证减速平滑 currentRotationSpeed = Mathf.Lerp(maxRotationSpeed, 0, timer / timeToDecelerate); cameraTransform.RotateAround(transform.position, Vector3.up, currentRotationSpeed * rotationDirection * Time.deltaTime); yield return null; } // 减速完成后固定转速为0 currentRotationSpeed = 0; } }
关键修改说明
- 新增
timeToDecelerate变量:可视化控制减速时长,方便调整平滑度。 - 用
rotationDirection替代原changeDir:用整数1/-1直接控制旋转方向,逻辑更直观,避免状态判断混乱。 - 拆分旋转流程为两个明确阶段:
- 加速阶段:保持原逻辑从初始转速平滑提升到最大值。
- 切换减速阶段:先反转方向,再通过
Mathf.Lerp将转速从最大值线性降到0,彻底解决负转速递增的问题。
- 移除无限循环:减速完成后直接停止旋转,完全匹配需求中"减速至0"的目标(若需要循环切换方向,可在减速完成后重新调用加速/减速逻辑)。
内容的提问来源于stack exchange,提问作者Daniel Lip
相关产品推荐
相关产品推荐

