//-------------------------------------------------------- // [Author]: 玩个游戏 // [ Date ]: Saturday, October 07, 2017 //-------------------------------------------------------- using System; using System.Collections; using System.Collections.Generic; using Cysharp.Threading.Tasks; using UnityEngine; using UnityEngine.UI; public class ScrollTipWin : UIBase { [SerializeField] RectTransform content; [SerializeField] RectTransform mask; [SerializeField, Header("显示条数")] int tipDisplayCnt = 3; [SerializeField, Header("每次滚动的距离")] float m_TipDistance = 50.0f; [SerializeField, Header("提示预制体高度")] float m_TipHeight = 40.0f; [SerializeField, Header("显示时间")] float m_TipShowTime = 1.0f; [SerializeField, Header("移动时间")] float m_TipMoveTime = 0.2f; [SerializeField, Header("隐藏时间")] float m_TipHideTime = 0.5f; bool isLoopRunning = false; protected override void InitComponent() { } protected override void OnClose() { } protected override void OnOpen() { } protected override void OnPreClose() { ScrollTip.OnTipReceiveEvent -= OnAddTipEvent; ScrollTip.ReleaseAll(); } protected override void OnPreOpen() { ScrollTip.tipMoveTime = m_TipMoveTime; ScrollTip.OnTipReceiveEvent += OnAddTipEvent; mask.sizeDelta = mask.sizeDelta.SetY(tipDisplayCnt * m_TipHeight + (tipDisplayCnt - 1) * (m_TipDistance - m_TipHeight) + 10); // 如果有待处理的提示,立即启动循环 if (ScrollTip.m_Hints.Count > 0) { LoopTipReceiveEvent().Forget(); } } async UniTask LoopTipReceiveEvent() { if (isLoopRunning) return; // 防止重复启动 isLoopRunning = true; try { while (ScrollTip.m_Hints.Count > 0) { OnTipReceiveEvent().Forget(); await UniTask.Delay(100); if (this == null) return; // destroyed during await } } finally { isLoopRunning = false; } } void OnAddTipEvent() { // 只有在没有循环运行时才启动新的循环 if (!isLoopRunning) { LoopTipReceiveEvent().Forget(); } } private async UniTask OnTipReceiveEvent() { if (ScrollTip.m_Hints.Count > 0 && IsCanAdd()) { if (ScrollTip.m_ActiveTips.Count >= tipDisplayCnt) { ScrollTip.Release(ScrollTip.m_ActiveTips[0], false); ScrollTip.tipMoveTime = Time.deltaTime; } else { ScrollTip.tipMoveTime = m_TipMoveTime; } // for (int i = 0; i < ScrollTip.m_ActiveTips.Count; i++) // { // ScrollTip.m_ActiveTips[i].Play(ScrollTip.ScrollTipState.Move); // } ScrollTipDetail tipDetail = await ScrollTip.Request(); if (tipDetail != null) { // 首次登录时 pool 为 null,Request() 异步加载预制体耗时 >100ms。 // LoopTipReceiveEvent 每 100ms 重入,可能已有另一次调用先消耗了 m_Hints[0]。 // 若 await 返回时 m_Hints 已空,必须将 tipDetail 归还池,否则它会被插入 Canvas 但 // 永远不会播放动画,导致提示条卡在屏幕上(第一次登录复现的根因)。 if (ScrollTip.m_Hints.Count == 0) { ScrollTip.Release(tipDetail, false); return; } tipDetail.SetTipConfig(m_TipShowTime, m_TipHideTime, m_TipDistance); ScrollTip.m_ActiveTips.Add(tipDetail); var rt = tipDetail.transform; rt.SetParent(content.parent); rt.localScale = Vector3.one; rt.localPosition = content.localPosition; var _hint = ScrollTip.m_Hints[0]; ScrollTip.m_Hints.RemoveAt(0); tipDetail.ShowTip(_hint); tipDetail.Play(ScrollTip.ScrollTipState.Move); } } } private bool IsCanAdd() { // for (int i = 0; i < ScrollTip.m_ActiveTips.Count; i++) // { // if (ScrollTip.m_ActiveTips[i].presentState == ScrollTip.ScrollTipState.Move) // { // return false; // } // } return true; } }