using UnityEngine;
|
using System;
|
|
/// <summary>
|
/// 战斗飘字UI控制器
|
/// 职责:处理飘字的缩放、透明度、位置动画逻辑
|
/// </summary>
|
[Serializable]
|
public class BattleFloatingUIController
|
{
|
#region 私有字段
|
|
private FloatingConfig config;
|
private RectTransform rectTransform;
|
private GameObject gameObject;
|
private Action<Color> 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<Color> applyColor,
|
FloatingConfig cfg)
|
{
|
rectTransform = rect;
|
gameObject = go;
|
applyColorCallback = applyColor;
|
config = cfg;
|
}
|
|
#endregion
|
|
#region 配置管理
|
|
/// <summary>
|
/// 设置或更新配置
|
/// </summary>
|
public void SetConfig(FloatingConfig cfg)
|
{
|
config = cfg;
|
}
|
|
/// <summary>
|
/// 设置运行时位置覆盖(会覆盖配置中的位置)
|
/// </summary>
|
public void SetRuntimePosition(Vector2 beginPos, Vector2 endPos)
|
{
|
runtimeBeginPos = beginPos;
|
runtimeEndPos = endPos;
|
}
|
|
/// <summary>
|
/// 清除运行时位置覆盖,恢复使用配置中的位置
|
/// </summary>
|
public void ClearRuntimePosition()
|
{
|
runtimeBeginPos = null;
|
runtimeEndPos = null;
|
}
|
|
/// <summary>
|
/// 设置运行时颜色覆盖(会覆盖配置中的颜色)
|
/// </summary>
|
public void SetRuntimeColor(Color beginColor, Color endColor)
|
{
|
runtimeBeginColor = beginColor;
|
runtimeEndColor = endColor;
|
}
|
|
/// <summary>
|
/// 清除运行时颜色覆盖,恢复使用配置中的颜色
|
/// </summary>
|
public void ClearRuntimeColor()
|
{
|
runtimeBeginColor = null;
|
runtimeEndColor = null;
|
}
|
|
#endregion
|
|
#region 播放控制
|
|
/// <summary>
|
/// 设置速度和缩放比例
|
/// </summary>
|
public void SetRatio(float speed, float scale)
|
{
|
speedRatio = speed;
|
scaleRatio = scale;
|
}
|
|
/// <summary>
|
/// 开始播放动画
|
/// </summary>
|
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);
|
}
|
|
/// <summary>
|
/// 每帧更新
|
/// </summary>
|
public void Run()
|
{
|
if (!gameObject.activeSelf || !ValidateConfig())
|
return;
|
|
// 检查是否完成
|
if (timer >= config.totalShowTime)
|
{
|
OnAnimationComplete();
|
return;
|
}
|
|
// 更新动画
|
UpdatePosition();
|
UpdateScaleAndColor();
|
|
// 增加计时器
|
timer += GetDeltaTime();
|
}
|
|
/// <summary>
|
/// 暂停(预留接口)
|
/// </summary>
|
public void Stop()
|
{
|
// 可以添加暂停逻辑
|
}
|
|
/// <summary>
|
/// 恢复(预留接口)
|
/// </summary>
|
public void Resume()
|
{
|
// 可以添加恢复逻辑
|
}
|
|
#endregion
|
|
#region 私有方法
|
|
/// <summary>
|
/// 验证配置有效性
|
/// </summary>
|
private bool ValidateConfig()
|
{
|
if (config == null)
|
{
|
Debug.LogError("[BattleFloatingUIController] FloatingConfig 配置为空");
|
return false;
|
}
|
return true;
|
}
|
|
/// <summary>
|
/// 获取起始位置(运行时位置优先)
|
/// </summary>
|
private Vector2 GetBeginPosition()
|
{
|
return runtimeBeginPos ?? config.beginPos;
|
}
|
|
/// <summary>
|
/// 获取结束位置(运行时位置优先)
|
/// </summary>
|
private Vector2 GetEndPosition()
|
{
|
return runtimeEndPos ?? config.endPos;
|
}
|
|
/// <summary>
|
/// 获取起始缩放
|
/// </summary>
|
private Vector3 GetBeginScale()
|
{
|
return isCritical ? config.critBeginScale : config.normalBeginScale;
|
}
|
|
/// <summary>
|
/// 获取结束缩放
|
/// </summary>
|
private Vector3 GetEndScale()
|
{
|
return isCritical ? config.critEndScale : config.normalEndScale;
|
}
|
|
/// <summary>
|
/// 获取时间增量
|
/// </summary>
|
private float GetDeltaTime()
|
{
|
return 1f / BattleConst.skillMotionFps * speedRatio;
|
}
|
|
/// <summary>
|
/// 更新位置
|
/// </summary>
|
private void UpdatePosition()
|
{
|
float timeProgress = timer / config.totalShowTime;
|
// 使用曲线来调整插值进度
|
float curveProgress = config.positionCurve.Evaluate(timeProgress);
|
Vector2 currentPos = Vector2.Lerp(GetBeginPosition(), GetEndPosition(), curveProgress);
|
rectTransform.anchoredPosition = currentPos;
|
}
|
|
/// <summary>
|
/// 获取起始颜色(运行时颜色优先)
|
/// </summary>
|
private Color GetBeginColor()
|
{
|
return runtimeBeginColor ?? config.beginColor;
|
}
|
|
/// <summary>
|
/// 获取结束颜色(运行时颜色优先)
|
/// </summary>
|
private Color GetEndColor()
|
{
|
return runtimeEndColor ?? config.endColor;
|
}
|
|
/// <summary>
|
/// 更新缩放和颜色
|
/// </summary>
|
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());
|
}
|
}
|
|
/// <summary>
|
/// 动画完成回调
|
/// </summary>
|
private void OnAnimationComplete()
|
{
|
gameObject.SetActive(false);
|
onFinishCallback?.Invoke();
|
onFinishCallback = null;
|
}
|
|
#endregion
|
}
|