2026-04-01 19:15:20 +08:00

133 lines
3.7 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using UnityEngine;
using System; // 必须引入 System 命名空间以使用 Action
using System.Collections;
public class YAxisRotator : MonoBehaviour
{
[Header("旋转设置")]
[Tooltip("旋转速度,度数/秒")]
public float rotationSpeed = 90f;
[Tooltip("判断是否到达目标角度的误差范围 (度)")]
public float angleThreshold = 0.5f;
private Coroutine _currentRotationCoroutine = null;
private float _targetAngle = 0f;
void Start()
{
_targetAngle = transform.localEulerAngles.y;
}
/// <summary>
/// 方法1旋转到180度
/// </summary>
/// <param name="onComplete">旋转完成后(或无需旋转时)执行的回调函数</param>
public void RotateTo180(Action onComplete = null)
{
// 检查是否已经接近180度
if (IsAngleClose(180f))
{
Debug.Log($"[{gameObject.name}] 已经在180度附近跳过旋转直接触发回调。");
_targetAngle = 180f;
// 【修改点】即使无需旋转,也立即触发回调
onComplete?.Invoke();
return;
}
// 如果正在旋转,先打断之前的旋转
if (_currentRotationCoroutine != null)
{
StopCoroutine(_currentRotationCoroutine);
// 注意:被打断的旧旋转不会触发回调,只有最终完成的那个会触发
}
_targetAngle = 180f;
_currentRotationCoroutine = StartCoroutine(RotateRoutine(180f, onComplete));
}
/// <summary>
/// 方法2旋转到0度
/// </summary>
/// <param name="onComplete">旋转完成后(或无需旋转时)执行的回调函数</param>
public void RotateTo0(Action onComplete = null)
{
// 检查是否已经接近0度
if (IsAngleClose(0f))
{
Debug.Log($"[{gameObject.name}] 已经在0度附近跳过旋转直接触发回调。");
_targetAngle = 0f;
// 【修改点】即使无需旋转,也立即触发回调
onComplete?.Invoke();
return;
}
if (_currentRotationCoroutine != null)
{
StopCoroutine(_currentRotationCoroutine);
}
_targetAngle = 0f;
_currentRotationCoroutine = StartCoroutine(RotateRoutine(0f, onComplete));
}
/// <summary>
/// 核心协程:执行平滑旋转
/// </summary>
private IEnumerator RotateRoutine(float targetY, Action onComplete)
{
while (true)
{
Vector3 currentEuler = transform.localEulerAngles;
float currentY = currentEuler.y;
// 计算最短路径角度差
float delta = Mathf.DeltaAngle(currentY, targetY);
// 到达目标判断
if (Mathf.Abs(delta) <= angleThreshold)
{
transform.localRotation = Quaternion.Euler(0, targetY, 0);
// 旋转结束,触发回调
onComplete?.Invoke();
_currentRotationCoroutine = null;
yield break;
}
float step = rotationSpeed * Time.deltaTime;
// 最后一步修正
if (Mathf.Abs(delta) < step)
{
transform.localRotation = Quaternion.Euler(0, targetY, 0);
// 旋转结束,触发回调
onComplete?.Invoke();
_currentRotationCoroutine = null;
yield break;
}
// 执行旋转
float newY = currentY + Mathf.Sign(delta) * step;
transform.localRotation = Quaternion.Euler(0, newY, 0);
yield return null;
}
}
/// <summary>
/// 辅助判断角度是否接近
/// </summary>
private bool IsAngleClose(float target)
{
float currentY = transform.localEulerAngles.y;
float delta = Mathf.DeltaAngle(currentY, target);
Debug.Log(delta);
return Mathf.Abs(delta) <= angleThreshold;
}
}