前提:必须包含DOTween插件,当然,如果不用插件做缓动动画,也可以用animation动画自定义相对应的缓动效果:
效果:
其实这个也挺简单的,用了两个队列(其中一个我还是使用了list),一个是消息显示队列,一个是消息缓存对象池(隐藏)。
我用的是Resources.Load加载的预制体
_layer 是我自定义划分的消息动画层(一个画布Canvas)
代码比较简单,我就不说了:
using DG.Tweening;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using view;
public class MessageMgr : MonoSingleton<MessageMgr>
{
//消息本体
private Text itemText;
/// <summary>
/// 消息列表
/// </summary>
private List<MessageItem> ItemList;
/// <summary>
/// 回收列表
/// </summary>
private Queue<MessageItem> QueText;
private GameObject _layer;
private Vector2 StartPos;
//文本高度
public float texHeight;
public float MessLine;
private int maxMsg;
private void Awake()
{
itemText = Resources.Load<Text>(UrlUntil.Instance.getUIPath() + "MessItem");
ItemList = new List<MessageItem>();
QueText = new Queue<MessageItem>();
//5添加到消息层
_layer = UIMgr.Instance.getGameObjectType(UIType.MESSAGE);
//StartPos = new Vector2(App.Instance.ScreenW / 2, App.Instance.ScreenH / 2);
StartPos = new Vector2(0, 0);
texHeight = 30;
//消息间隔
MessLine = 15;
//最多显示消息
maxMsg = 10;
}
private MessageItem GetItem()
{
MessageItem item = null;
//如果队列中有就返回出去
if (QueText.Count > 0)
{
item = QueText.Dequeue();
}
//没有就复制一个
else
{
//超过限制就取最上面的一个
if (ItemList.Count >= maxMsg)
{
item = ItemList[0];
ItemList.RemoveAt(0);
}
else
{
item = new MessageItem(Instantiate(itemText));
}
}
item.transform.gameObject.SetActive(true);
ItemList.Add(item);
return item;
}
/// <summary>
/// 显示相对应的消息
/// </summary>
/// <param name="message"></param>
/// <param name="color"></param>
public void showMessage(string message,Color color=default(Color))
{
MessageItem item = GetItem();
if (item == null) return;
if (item.transform.parent == null)
{
item.transform.SetParent(_layer.transform,false);
}
//Debug.Log(item.transform.localPosition + "---" + StartPos);
item.transform.localPosition = StartPos;
item.show(message, QueText, ItemList, color);
updataMsgY();
}
/// <summary>
/// 坐标移动
/// </summary>
private void updataMsgY()
{
for (int i = 0; i < ItemList.Count; i++)
{
float pos = StartPos.y + texHeight * (ItemList.Count - i) + MessLine;
ItemList[i].UpDataY(pos, i);
}
}
}
item消息类:
缓动动画在播放前一定要杀死动画,清空动画队列。
里面的有些参数可以根据自己需要提升成成员变量。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using DG.Tweening;
public class MessageItem
{
public string msgKey;
Text text;
public Sequence twQue;
public MessageItem(Text tex)
{
text = tex;
}
public Transform transform
{
get { return text.transform; }
}
/// <summary>
/// 更新Y坐标
/// </summary>
/// <param name="movY"></param>
public void UpDataY(float movY,int id)
{
//移动前必须杀死动画
text.transform.DOKill();
text.transform.DOLocalMoveY(movY, 0.5f);
}
/// <summary>
/// 3秒隐身
/// </summary>
public void show(string msg, Queue<MessageItem> que, List<MessageItem> list,Color color)
{
setMsg(msg, color);
text.color = new Color(text.color.r, text.color.g, text.color.b, 1);
Color tagcol = text.color * new Color(1, 1, 1, 0);
//动画队列
//DOTween.Kill(twQue);
twQue.Kill();
twQue = DOTween.Sequence();
//twQue.SetId(list.IndexOf(this));
//间隔3秒隐身
twQue.AppendInterval(3);
twQue.Append(text.DOColor(tagcol, 0.5f));
//隐身后添加到队列
twQue.AppendCallback(() =>
{
Debug.Log("DOTween动画播放完");
text.gameObject.SetActive(false);
if (!que.Contains(this))
{
que.Enqueue(this);
list.Remove(this);
}
});
}
/// <summary>
/// 设置文本信息
/// </summary>
/// <param name="msg"></param>
private void setMsg(string msg,Color color)
{
this.text.text = msg;
this.text.color = color;
}
}