dezhou_client/wb_unity_pro/Assets/Scripts/LuaHelper/LuaUIHelper.cs

446 lines
13 KiB
C#
Raw Normal View History

2025-12-17 21:08:27 +08:00
using LuaInterface;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.UI;
public class LuaUIHelper : MonoBehaviour
{
#region 消息提示
private float messageDuration = 2f; // 单条消息显示时间
private float appearDuration = 0.3f; // 出现动画时间
private float disappearDuration = 0.5f; // 消失动画时间
private float startYPosition = -100f; // 起始Y位置底部
private float moveSpeed = 8f; // 位置移动速度
private float spacingMultiplier = 1.2f; // 间距倍数(基于消息高度)
private GameObject msgPrefab;
private Stack<MessageItem> msgPool = new Stack<MessageItem>();
private List<MessageItem> activeMessages = new List<MessageItem>();
private float messageHeight = 60f; // 消息预制体的高度(运行时获取)
private bool isInitialized = false;
// 消息全部消失时的回调
private LuaFunction onAllMessagesDisappeared;
// 初始化消息预制体,并设置消息全部消失时的回调
public void SetMsgPrefab(GameObject prefab, LuaFunction onMsgEnd)
{
msgPrefab = prefab;
// 设置回调
onAllMessagesDisappeared = onMsgEnd;
// 获取预制体的高度
RectTransform prefabRect = prefab.GetComponent<RectTransform>();
if (prefabRect != null)
{
messageHeight = prefabRect.rect.height;
}
// 获取Image组件的高度如果有
Image image = prefab.GetComponent<Image>();
if (image != null)
{
RectTransform imageRect = image.GetComponent<RectTransform>();
messageHeight = imageRect.rect.height;
}
isInitialized = true;
}
// 显示消息
public void ShowInfo(string strMsg)
{
if (!isInitialized)
{
return;
}
MessageItem msg = GetMessageItem();
msg.Initialize(strMsg, this, messageDuration);
// 新消息总是在列表的开头索引0表示最底部
activeMessages.Insert(0, msg);
// 更新所有消息的目标位置
UpdateAllTargetPositions();
// 开始显示新消息
StartCoroutine(msg.Show());
}
// 从池中获取消息项
private MessageItem GetMessageItem()
{
MessageItem msg;
if (msgPool.Count > 0)
{
msg = msgPool.Pop();
msg.gameObject.SetActive(true);
}
else
{
GameObject go = Instantiate(msgPrefab, msgPrefab.transform.parent, false);
msg = new MessageItem(go);
}
return msg;
}
// 计算消息之间的间距
private float GetSpacing()
{
return messageHeight * spacingMultiplier;
}
// 更新所有消息的目标位置
private void UpdateAllTargetPositions()
{
float spacing = GetSpacing();
// 列表索引0是最底部的消息最新
// 列表索引越大位置越高(越靠上)
for (int i = 0; i < activeMessages.Count; i++)
{
// 第i条消息的位置 = 起始位置 + (从底部算起的索引 * 间距)
float targetY = startYPosition + (i * spacing);
activeMessages[i].SetTargetY(targetY);
}
}
private void Update()
{
// 更新所有活跃消息的位置
for (int i = 0; i < activeMessages.Count; i++)
{
var msg = activeMessages[i];
// 更新消息的生命周期
msg.UpdateMessage(Time.deltaTime);
// 如果消息应该消失,开始消失动画
if (msg.ShouldDisappear() && msg.currentState != MessageState.Disappearing)
{
StartCoroutine(HandleMessageDisappear(msg));
}
// 更新消息位置(平滑移动)
if (msg.currentState == MessageState.Active || msg.currentState == MessageState.Appearing)
{
msg.UpdatePosition(Time.deltaTime * moveSpeed);
}
}
}
// 处理消息消失
private IEnumerator HandleMessageDisappear(MessageItem msg)
{
// 开始消失动画
yield return StartCoroutine(msg.Disappear());
// 从活跃列表中移除
if (activeMessages.Contains(msg))
{
activeMessages.Remove(msg);
// 回收消息到对象池
ReturnToPool(msg);
// 重新计算剩余消息的位置
UpdateAllTargetPositions();
// 检查是否所有消息都消失了
CheckAllMessagesDisappeared();
}
}
// 检查是否所有消息都消失了
private void CheckAllMessagesDisappeared()
{
if (activeMessages.Count == 0 && onAllMessagesDisappeared != null)
{
onAllMessagesDisappeared.Call();
}
}
// 回收消息项到池中
private void ReturnToPool(MessageItem msg)
{
msg.gameObject.SetActive(false);
msg.Reset();
msgPool.Push(msg);
}
// 消息状态枚举
private enum MessageState
{
WaitingToShow, // 等待显示
Appearing, // 出现中
Active, // 活跃中
Disappearing // 消失中
}
// 消息项类
private class MessageItem
{
public GameObject gameObject;
public RectTransform rect;
public Text text;
public CanvasGroup canvasGroup;
public Image backgroundImage; // 背景图片
private LuaUIHelper manager;
private MessageState _currentState = MessageState.WaitingToShow;
public MessageState currentState => _currentState;
private float currentY; // 当前Y位置
private float targetY; // 目标Y位置
private float appearProgress; // 出现进度
private float lifeTime; // 生命周期计时器
private float maxLifeTime; // 最大生命周期
public MessageItem(GameObject go)
{
gameObject = go;
rect = go.GetComponent<RectTransform>();
text = go.transform.GetChild(0).GetComponent<Text>();
// 获取背景图片
backgroundImage = go.GetComponent<Image>();
// 添加或获取CanvasGroup
canvasGroup = go.GetComponent<CanvasGroup>();
if (canvasGroup == null)
canvasGroup = go.AddComponent<CanvasGroup>();
}
// 初始化消息
public void Initialize(string message, LuaUIHelper manager, float duration)
{
this.manager = manager;
this.maxLifeTime = duration;
text.text = message;
// 重置状态
_currentState = MessageState.WaitingToShow;
appearProgress = 0f;
lifeTime = 0f;
// 新消息从屏幕外更底部开始
float spacing = manager.GetSpacing();
currentY = manager.startYPosition - spacing - 50f;
rect.anchoredPosition = new Vector2(0, currentY);
canvasGroup.alpha = 0f;
// 确保消息可见
if (backgroundImage != null)
{
backgroundImage.enabled = true;
}
gameObject.SetActive(true);
}
// 设置目标Y位置
public void SetTargetY(float y)
{
targetY = y;
}
// 更新消息生命周期
public void UpdateMessage(float deltaTime)
{
if (_currentState == MessageState.Active)
{
lifeTime += deltaTime;
}
}
// 检查是否应该消失
public bool ShouldDisappear()
{
return _currentState == MessageState.Active && lifeTime >= maxLifeTime;
}
// 显示消息
public IEnumerator Show()
{
_currentState = MessageState.Appearing;
// 出现动画:从下方滑入并淡入
float timer = 0f;
float startY = currentY;
while (timer < manager.appearDuration)
{
timer += Time.deltaTime;
appearProgress = timer / manager.appearDuration;
// 缓动函数EaseOutCubic
float easedProgress = 1f - Mathf.Pow(1f - appearProgress, 3);
// 位置动画(从下方滑入)
float newY = Mathf.Lerp(startY, targetY, easedProgress);
currentY = newY;
rect.anchoredPosition = new Vector2(0, newY);
// 透明度动画
canvasGroup.alpha = Mathf.Lerp(0f, 1f, easedProgress);
yield return null;
}
// 进入活跃状态
_currentState = MessageState.Active;
currentY = targetY;
rect.anchoredPosition = new Vector2(0, targetY);
canvasGroup.alpha = 1f;
// 重置生命周期计时器
lifeTime = 0f;
}
// 消失动画
public IEnumerator Disappear()
{
_currentState = MessageState.Disappearing;
// 向上淡出消失
float timer = 0f;
float startY = currentY;
float disappearY = startY + 50f; // 向上移动消失
while (timer < manager.disappearDuration)
{
timer += Time.deltaTime;
float progress = timer / manager.disappearDuration;
// 缓动函数EaseInCubic
float easedProgress = Mathf.Pow(progress, 3);
// 位置动画(向上移动)
float newY = Mathf.Lerp(startY, disappearY, easedProgress);
rect.anchoredPosition = new Vector2(0, newY);
// 透明度动画
canvasGroup.alpha = Mathf.Lerp(1f, 0f, easedProgress);
yield return null;
}
// 完全消失
canvasGroup.alpha = 0f;
rect.anchoredPosition = new Vector2(0, disappearY);
}
// 更新位置(平滑移动到目标位置)
public void UpdatePosition(float speed)
{
if ((_currentState == MessageState.Active || _currentState == MessageState.Appearing) &&
Mathf.Abs(currentY - targetY) > 0.1f)
{
currentY = Mathf.Lerp(currentY, targetY, speed);
rect.anchoredPosition = new Vector2(0, currentY);
}
else if (_currentState == MessageState.Active)
{
currentY = targetY;
rect.anchoredPosition = new Vector2(0, targetY);
}
}
// 重置状态
public void Reset()
{
_currentState = MessageState.WaitingToShow;
appearProgress = 0f;
lifeTime = 0f;
canvasGroup.alpha = 0f;
// 重置位置到初始位置
rect.anchoredPosition = Vector2.zero;
}
}
#endregion
public Text[] GetAllText(GameObject go)
{
Text[] allTexts = go.GetComponentsInChildren<Text>(true);
return allTexts.Where(text => !text.CompareTag("untext")).ToArray();
}
public void DelayAction(float floTime, LuaFunction func)
{
StartCoroutine(_delayAction(floTime, func));
}
IEnumerator _delayAction(float floTime, LuaFunction func)
{
yield return new WaitForSeconds(floTime);
func.Call();
}
public void AddButtonClick(Button button, LuaFunction func)
{
if (button == null || func == null) return;
button.onClick.AddListener(() =>
{
func.Call();
});
}
public void AddButtonClickWithGameObject(Button button, LuaFunction func)
{
if (button == null || func == null) return;
GameObject go = button.gameObject;
button.onClick.AddListener(() =>
{
func.Call(go);
});
}
public void AddButtonClick(Button button, LuaFunction func, int index)
{
if (button == null || func == null) return;
button.onClick.AddListener(() =>
{
func.Call(index);
});
}
2025-12-19 20:03:24 +08:00
public void AddButtonClick(Button button, LuaFunction func, LuaTable ta)
{
if (button == null || func == null) return;
button.onClick.AddListener(() =>
{
func.Call(ta);
});
}
2025-12-17 21:08:27 +08:00
public float GetAnimatorAormalizedTime(Animator a, bool boo)
{
AnimatorStateInfo infor = a.GetCurrentAnimatorStateInfo(0);
if (boo)
{
return infor.normalizedTime;
}
return infor.normalizedTime % 1;
}
public float GetAnimtorTotalTime(Animator a)
{
AnimatorStateInfo infor = a.GetCurrentAnimatorStateInfo(0);
return infor.length;
}
public bool GetAnimatorIsName(Animator a, string strName)
{
return a.GetCurrentAnimatorStateInfo(0).IsName(strName);
}
public void SetGameObjectLastSibling(GameObject go)
{
go.transform.SetAsLastSibling();
}
}