| | |
| | | using System; |
| | | using UnityEngine.UI; |
| | | |
| | | public class BattleTips : MonoBehaviour |
| | | /// <summary> |
| | | /// 战斗飘字UI组件 |
| | | /// 职责:管理UI元素和与控制器的交互 |
| | | /// </summary> |
| | | public class BattleTips : MonoBehaviour, IBattleFloatingUI |
| | | { |
| | | public Vector2 beginPos = Vector2.zero; |
| | | public Vector2 endPos = new Vector2(0, 150); |
| | | |
| | | public float scaleChangeTime = 0.2667f; // 7~8帧 (8/30=0.2667秒) |
| | | public float totalShowTime = 0.8f; // 总时间约24帧 (8+16=24帧) |
| | | public float timer = 0f; |
| | | |
| | | public Vector3 beginScale = new Vector3(4f, 4f, 4f); |
| | | public Vector3 endScale = new Vector3(2f, 2f, 2f); |
| | | public Color beginColor = new Color(1f, 1f, 1f, 0.5f); |
| | | public Color endColor = new Color(1f, 1f, 1f, 1f); |
| | | |
| | | #region Inspector字段 |
| | | |
| | | [Header("UI Components")] |
| | | public RectTransform rectTransform; |
| | | |
| | | public Text tipText; |
| | | |
| | | public Text artText; |
| | | public Image background; |
| | | |
| | | [Header("Floating Config")] |
| | | [Tooltip("飘字动画配置,请在Inspector中拖拽赋值")] |
| | | public FloatingConfig floatingConfig; |
| | | |
| | | #endregion |
| | | |
| | | #region 公共字段 |
| | | |
| | | public Action OnFinish; |
| | | |
| | | // Buff 颜色相关 |
| | | private bool useBuffColor = false; |
| | | private bool isDebuff = false; |
| | | |
| | | #endregion |
| | | |
| | | private float speedRatio = 1f; |
| | | #region 私有字段 |
| | | |
| | | // 移除 [SerializeField],controller 不应该被序列化 |
| | | public BattleFloatingUIController controller; |
| | | |
| | | #endregion |
| | | |
| | | public void SetSpeedRatio(float ratio) |
| | | |
| | | #region 公共方法 |
| | | |
| | | /// <summary> |
| | | /// 设置速度和缩放比例 |
| | | /// </summary> |
| | | public void SetRatio(float speed, float scale) |
| | | { |
| | | speedRatio = ratio; |
| | | EnsureControllerInitialized(); |
| | | controller?.SetRatio(speed, scale); |
| | | } |
| | | |
| | | public void SetText(string text, bool useArtText = false) |
| | | /// <summary> |
| | | /// 设置运行时位置(用于不跟随角色的飘字) |
| | | /// </summary> |
| | | public void SetPosition(Vector2 beginPos, Vector2 endPos) |
| | | { |
| | | // 初始放大200% 透明度50% 7~8帧内缩回100% 透明度到100% 再往上飘14~16帧 然后消失 (30帧/秒) |
| | | |
| | | // 8+16/30=0.8秒 |
| | | EnsureControllerInitialized(); |
| | | controller?.SetRuntimePosition(beginPos, endPos); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 运行时更新配置 |
| | | /// </summary> |
| | | public void SetFloatingConfig(FloatingConfig config) |
| | | { |
| | | floatingConfig = config; |
| | | |
| | | if (controller != null) |
| | | { |
| | | controller.SetConfig(config); |
| | | } |
| | | else |
| | | { |
| | | InitController(); |
| | | } |
| | | } |
| | | |
| | | rectTransform.anchoredPosition = beginPos; |
| | | rectTransform.localScale = beginScale; |
| | | /// <summary> |
| | | /// 设置是否使用 Buff 颜色 |
| | | /// </summary> |
| | | public void SetBuffColor(bool useBuff, bool isDebuffBuff) |
| | | { |
| | | useBuffColor = useBuff; |
| | | isDebuff = isDebuffBuff; |
| | | |
| | | // 如果使用 buff 颜色,立即设置运行时颜色覆盖 |
| | | if (useBuffColor && floatingConfig != null) |
| | | { |
| | | Color buffColor = isDebuff ? floatingConfig.debuffColor : floatingConfig.gainBuffColor; |
| | | Color beginColor = new Color(buffColor.r, buffColor.g, buffColor.b, floatingConfig.beginColor.a); |
| | | Color endColor = new Color(buffColor.r, buffColor.g, buffColor.b, floatingConfig.endColor.a); |
| | | |
| | | EnsureControllerInitialized(); |
| | | controller?.SetRuntimeColor(beginColor, endColor); |
| | | } |
| | | } |
| | | |
| | | timer = 0f; |
| | | gameObject.SetActive(true); |
| | | /// <summary> |
| | | /// 设置文本内容和样式 |
| | | /// </summary> |
| | | public void SetText(string text, bool useArtText = false, bool isCrit = false) |
| | | { |
| | | EnsureControllerInitialized(); |
| | | |
| | | // 切换文本显示类型 |
| | | SwitchTextDisplay(useArtText, text); |
| | | |
| | | // 开始播放 |
| | | Play(isCrit); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 显示/隐藏背景 |
| | | /// </summary> |
| | | public void ShowBackground(bool show) |
| | | { |
| | | if (background != null) |
| | | background.enabled = show; |
| | | } |
| | | |
| | | #endregion |
| | | |
| | | #region IBattleFloatingUI接口实现 |
| | | |
| | | public void Play(bool isCrit, Action onComplete = null) |
| | | { |
| | | EnsureControllerInitialized(); |
| | | |
| | | if (controller == null) return; |
| | | |
| | | // 合并回调 |
| | | Action combinedCallback = () => |
| | | { |
| | | OnFinish?.Invoke(); |
| | | OnFinish = null; |
| | | onComplete?.Invoke(); |
| | | }; |
| | | |
| | | controller.Play(isCrit, combinedCallback); |
| | | } |
| | | |
| | | public void Run() |
| | | { |
| | | controller?.Run(); |
| | | } |
| | | |
| | | public void Stop() |
| | | { |
| | | controller?.Stop(); |
| | | } |
| | | |
| | | public void Resume() |
| | | { |
| | | controller?.Resume(); |
| | | } |
| | | |
| | | #endregion |
| | | |
| | | #region 私有方法 |
| | | |
| | | /// <summary> |
| | | /// 初始化控制器 |
| | | /// </summary> |
| | | private void InitController() |
| | | { |
| | | if (floatingConfig == null) |
| | | { |
| | | Debug.LogError($"[BattleTips] FloatingConfig 未配置! GameObject: {gameObject.name}"); |
| | | return; |
| | | } |
| | | |
| | | controller = new BattleFloatingUIController( |
| | | rectTransform, |
| | | gameObject, |
| | | ApplyColor, |
| | | floatingConfig |
| | | ); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 确保控制器已初始化 |
| | | /// </summary> |
| | | private void EnsureControllerInitialized() |
| | | { |
| | | if (controller == null || !controller.IsValid()) |
| | | InitController(); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 切换文本显示类型 |
| | | /// </summary> |
| | | private void SwitchTextDisplay(bool useArtText, string text) |
| | | { |
| | | if (useArtText) |
| | | { |
| | | artText.text = text; |
| | | artText.color = beginColor; |
| | | tipText.gameObject.SetActive(false); |
| | | artText.gameObject.SetActive(true); |
| | | } |
| | | else |
| | | { |
| | | tipText.text = text; |
| | | tipText.color = beginColor; |
| | | artText.gameObject.SetActive(false); |
| | | tipText.gameObject.SetActive(true); |
| | | } |
| | | } |
| | | |
| | | |
| | | // 不要使用update |
| | | public void Run() |
| | | |
| | | /// <summary> |
| | | /// 应用文本颜色(保留配置的透明度) |
| | | /// </summary> |
| | | private void ApplyTextColor(Color textColor) |
| | | { |
| | | if (!gameObject.activeSelf) |
| | | return; |
| | | |
| | | if (timer >= totalShowTime) |
| | | if (floatingConfig != null) |
| | | { |
| | | gameObject.SetActive(false); |
| | | OnFinish?.Invoke(); |
| | | OnFinish = null; |
| | | return; |
| | | Color colorWithAlpha = new Color( |
| | | textColor.r, |
| | | textColor.g, |
| | | textColor.b, |
| | | floatingConfig.beginColor.a |
| | | ); |
| | | ApplyColor(colorWithAlpha); |
| | | } |
| | | |
| | | // 整个过程都往上飘 |
| | | float moveProgress = timer / totalShowTime; |
| | | rectTransform.anchoredPosition = Vector2.Lerp(beginPos, endPos, moveProgress); |
| | | |
| | | // 阶段1: 7~8帧内缩放从beginScale到endScale,透明度从50%到100% |
| | | if (timer < scaleChangeTime) |
| | | { |
| | | float scaleProgress = timer / scaleChangeTime; |
| | | rectTransform.localScale = Vector3.Lerp(beginScale, endScale, scaleProgress); |
| | | |
| | | Color currentColor = Color.Lerp(beginColor, endColor, scaleProgress); |
| | | if (tipText.gameObject.activeSelf) |
| | | tipText.color = currentColor; |
| | | if (artText.gameObject.activeSelf) |
| | | artText.color = currentColor; |
| | | } |
| | | // 阶段2: 缩放完成后,保持endScale和100%透明度,继续往上飘 |
| | | else |
| | | { |
| | | rectTransform.localScale = endScale; |
| | | |
| | | if (tipText.gameObject.activeSelf) |
| | | tipText.color = endColor; |
| | | if (artText.gameObject.activeSelf) |
| | | artText.color = endColor; |
| | | } |
| | | |
| | | timer += 1f / (float)BattleConst.skillMotionFps * speedRatio; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 应用颜色到激活的文本组件 |
| | | /// </summary> |
| | | private void ApplyColor(Color color) |
| | | { |
| | | if (tipText.gameObject.activeSelf) |
| | | tipText.color = color; |
| | | |
| | | if (artText.gameObject.activeSelf) |
| | | artText.color = color; |
| | | } |
| | | |
| | | #endregion |
| | | } |