using UnityEngine;
using System;
///
/// 战斗飘字UI控制器
/// 职责:处理飘字的缩放、透明度、位置动画逻辑
///
[Serializable]
public class BattleFloatingUIController
{
#region 私有字段
private FloatingConfig config;
private RectTransform rectTransform;
private GameObject gameObject;
private Action applyColorCallback;
// 运行时状态
private float timer = 0f;
private float speedRatio = 1f;
private float scaleRatio = 1f;
private bool isCritical = false;
private Action onFinishCallback;
// 运行时位置覆盖(优先级高于配置)
private Vector2? runtimeBeginPos = null;
private Vector2? runtimeEndPos = null;
// 运行时颜色覆盖(优先级高于配置)
private Color? runtimeBeginColor = null;
private Color? runtimeEndColor = null;
#endregion
#region 公共属性
public float Timer => timer;
public float SpeedRatio => speedRatio;
public float ScaleRatio => scaleRatio;
#endregion
#region 构造函数
public BattleFloatingUIController(
RectTransform rect,
GameObject go,
Action applyColor,
FloatingConfig cfg)
{
rectTransform = rect;
gameObject = go;
applyColorCallback = applyColor;
config = cfg;
}
#endregion
#region 配置管理
///
/// 设置或更新配置
///
public void SetConfig(FloatingConfig cfg)
{
config = cfg;
}
///
/// 设置运行时位置覆盖(会覆盖配置中的位置)
///
public void SetRuntimePosition(Vector2 beginPos, Vector2 endPos)
{
runtimeBeginPos = beginPos;
runtimeEndPos = endPos;
}
///
/// 清除运行时位置覆盖,恢复使用配置中的位置
///
public void ClearRuntimePosition()
{
runtimeBeginPos = null;
runtimeEndPos = null;
}
///
/// 设置运行时颜色覆盖(会覆盖配置中的颜色)
///
public void SetRuntimeColor(Color beginColor, Color endColor)
{
runtimeBeginColor = beginColor;
runtimeEndColor = endColor;
}
///
/// 清除运行时颜色覆盖,恢复使用配置中的颜色
///
public void ClearRuntimeColor()
{
runtimeBeginColor = null;
runtimeEndColor = null;
}
#endregion
#region 播放控制
///
/// 设置速度和缩放比例
///
public void SetRatio(float speed, float scale)
{
speedRatio = speed;
scaleRatio = scale;
}
///
/// 开始播放动画
///
public void Play(bool isCrit, Action onComplete = null)
{
if (!ValidateConfig()) return;
isCritical = isCrit;
onFinishCallback = onComplete;
timer = 0f;
// 初始化位置和缩放
Vector2 beginPos = GetBeginPosition();
Vector3 beginScale = GetBeginScale();
rectTransform.anchoredPosition = beginPos;
rectTransform.localScale = beginScale * scaleRatio;
gameObject.SetActive(true);
}
///
/// 每帧更新
///
public void Run()
{
if (!gameObject.activeSelf || !ValidateConfig())
return;
// 检查是否完成
if (timer >= config.totalShowTime)
{
OnAnimationComplete();
return;
}
// 更新动画
UpdatePosition();
UpdateScaleAndColor();
// 增加计时器
timer += GetDeltaTime();
}
///
/// 暂停(预留接口)
///
public void Stop()
{
// 可以添加暂停逻辑
}
///
/// 恢复(预留接口)
///
public void Resume()
{
// 可以添加恢复逻辑
}
#endregion
#region 私有方法
///
/// 验证配置有效性
///
private bool ValidateConfig()
{
if (config == null)
{
Debug.LogError("[BattleFloatingUIController] FloatingConfig 配置为空");
return false;
}
return true;
}
///
/// 获取起始位置(运行时位置优先)
///
private Vector2 GetBeginPosition()
{
return runtimeBeginPos ?? config.beginPos;
}
///
/// 获取结束位置(运行时位置优先)
///
private Vector2 GetEndPosition()
{
return runtimeEndPos ?? config.endPos;
}
///
/// 获取起始缩放
///
private Vector3 GetBeginScale()
{
return isCritical ? config.critBeginScale : config.normalBeginScale;
}
///
/// 获取结束缩放
///
private Vector3 GetEndScale()
{
return isCritical ? config.critEndScale : config.normalEndScale;
}
///
/// 获取时间增量
///
private float GetDeltaTime()
{
return 1f / BattleConst.skillMotionFps * speedRatio;
}
///
/// 更新位置
///
private void UpdatePosition()
{
float timeProgress = timer / config.totalShowTime;
// 使用曲线来调整插值进度
float curveProgress = config.positionCurve.Evaluate(timeProgress);
Vector2 currentPos = Vector2.Lerp(GetBeginPosition(), GetEndPosition(), curveProgress);
rectTransform.anchoredPosition = currentPos;
}
///
/// 获取起始颜色(运行时颜色优先)
///
private Color GetBeginColor()
{
return runtimeBeginColor ?? config.beginColor;
}
///
/// 获取结束颜色(运行时颜色优先)
///
private Color GetEndColor()
{
return runtimeEndColor ?? config.endColor;
}
///
/// 更新缩放和颜色
///
private void UpdateScaleAndColor()
{
// 阶段1: 缩放和透明度变化
if (timer < config.scaleChangeTime)
{
float timeProgress = timer / config.scaleChangeTime;
// 根据是否暴击选择对应的缩放曲线
AnimationCurve scaleCurve = isCritical ? config.critScaleCurve : config.normalScaleCurve;
float scaleProgress = scaleCurve.Evaluate(timeProgress);
Vector3 currentScale = Vector3.Lerp(GetBeginScale(), GetEndScale(), scaleProgress);
rectTransform.localScale = currentScale * scaleRatio;
// 使用曲线来调整颜色插值进度
float colorProgress = config.colorCurve.Evaluate(timeProgress);
Color currentColor = Color.Lerp(GetBeginColor(), GetEndColor(), colorProgress);
applyColorCallback?.Invoke(currentColor);
}
// 阶段2: 保持最终缩放和透明度
else
{
rectTransform.localScale = GetEndScale() * scaleRatio;
applyColorCallback?.Invoke(GetEndColor());
}
}
///
/// 动画完成回调
///
private void OnAnimationComplete()
{
gameObject.SetActive(false);
onFinishCallback?.Invoke();
onFinishCallback = null;
}
#endregion
}