Files
aibis-dream/Assets/Scripts/Framework/OtherKit/ThreeStatePositionMover.cs
T
2026-01-22 18:16:11 +08:00

219 lines
6.0 KiB
C#

using UnityEngine;
using DG.Tweening;
namespace AibisDream
{
/// <summary>
/// 三状态位置移动器
/// 提供Open、Close、Half三个目标位置,使用DOTween进行平滑移动
/// 移动过程不可被打断,并提供移动状态标记
/// </summary>
public class ThreeStatePositionMover : MonoBehaviour
{
[Header("目标位置设置")]
[SerializeField] private Transform openPosition;
[SerializeField] private Transform closePosition;
[SerializeField] private Transform halfPosition;
[Header("移动设置")]
[SerializeField] private float moveDuration = 0.5f;
[SerializeField] private Ease moveEase = Ease.OutQuad;
// 当前状态
private PositionState _currentState = PositionState.Close;
// 当前正在执行的Tween
private Tween _currentTween;
// 是否正在移动中
public bool IsMoving { get; private set; }
private void Awake()
{
// 初始化时设置到Close位置
if (closePosition != null)
{
transform.position = closePosition.position;
}
}
private void OnDestroy()
{
// 清理Tween
if (_currentTween != null)
{
_currentTween.Kill();
_currentTween = null;
}
}
/// <summary>
/// 设置到Open状态
/// </summary>
public void SetToOpen()
{
MoveToState(PositionState.Open);
}
/// <summary>
/// 设置到Close状态
/// </summary>
public void SetToClose()
{
MoveToState(PositionState.Close);
}
/// <summary>
/// 设置到Half状态
/// </summary>
public void SetToHalf()
{
MoveToState(PositionState.Half);
}
/// <summary>
/// 移动到指定状态
/// </summary>
/// <param name="targetState">目标状态</param>
public void MoveToState(PositionState targetState)
{
// 如果正在移动中,忽略新的移动请求
if (IsMoving)
{
return;
}
// 如果已经是目标状态,直接返回
if (_currentState == targetState)
{
return;
}
// 获取目标Transform
Transform targetTransform = GetTransformForState(targetState);
if (targetTransform == null)
{
Debug.LogWarning($"ThreeStatePositionMover: {targetState} 状态的Transform未设置!");
return;
}
// 获取目标位置
Vector3 targetPosition = targetTransform.position;
// 如果当前有正在执行的Tween,先停止它
if (_currentTween != null && _currentTween.IsActive())
{
_currentTween.Kill();
}
// 设置移动状态
IsMoving = true;
// 创建新的Tween
_currentTween = transform.DOMove(targetPosition, moveDuration)
.SetEase(moveEase)
.OnComplete(() =>
{
IsMoving = false;
_currentState = targetState;
_currentTween = null;
});
}
/// <summary>
/// 立即设置到指定状态(不播放动画)
/// </summary>
/// <param name="targetState">目标状态</param>
public void SetStateImmediate(PositionState targetState)
{
// 如果正在移动,先停止移动
if (_currentTween != null && _currentTween.IsActive())
{
_currentTween.Kill();
_currentTween = null;
}
IsMoving = false;
_currentState = targetState;
Transform targetTransform = GetTransformForState(targetState);
if (targetTransform != null)
{
transform.position = targetTransform.position;
}
}
/// <summary>
/// 获取指定状态对应的Transform
/// </summary>
private Transform GetTransformForState(PositionState state)
{
return state switch
{
PositionState.Open => openPosition,
PositionState.Close => closePosition,
PositionState.Half => halfPosition,
_ => closePosition
};
}
/// <summary>
/// 获取当前状态
/// </summary>
public PositionState GetCurrentState()
{
return _currentState;
}
/// <summary>
/// 设置移动持续时间(运行时)
/// </summary>
public void SetMoveDuration(float duration)
{
moveDuration = duration;
}
/// <summary>
/// 设置缓动类型(运行时)
/// </summary>
public void SetMoveEase(Ease ease)
{
moveEase = ease;
}
#if UNITY_EDITOR
// 编辑器辅助:在Scene视图中显示目标位置
private void OnDrawGizmosSelected()
{
if (openPosition != null)
{
Gizmos.color = Color.green;
Gizmos.DrawWireSphere(openPosition.position, 0.1f);
}
if (closePosition != null)
{
Gizmos.color = Color.red;
Gizmos.DrawWireSphere(closePosition.position, 0.1f);
}
if (halfPosition != null)
{
Gizmos.color = Color.yellow;
Gizmos.DrawWireSphere(halfPosition.position, 0.1f);
}
}
#endif
}
/// <summary>
/// 位置状态枚举
/// </summary>
public enum PositionState
{
Open,
Close,
Half
}
}