当我们进入游戏大厅时,经常有各种弹窗、引导甚至插屏广告需要执行,处理不当时,会导致同时执行的情况,此时我们需要一个弹出管理器统一管理弹出顺序,弹出关闭后是否可以继续执行下一个弹出等。
配置表:
public partial class PopConfig{
// 属性定义
/// <summary>
/// 弹出唯一ID
/// </summary>
public string Id;
/// <summary>
/// 备注
/// </summary>
public string Des;
/// <summary>
/// 权重,权重越大,排序越靠前
/// </summary>
public int Weight;
/// <summary>
/// 关闭类型
///
/// 0.关闭后不执行其他操作
/// 1.关闭后触发下一个弹出
/// </summary>
public int CloseType;
// 函数接口
public static PopConfig[] GetDatas(){
return Datas;
}
// PopConfig 共计 [10] 条数据
public static PopConfig[] Datas = new PopConfig[]{
new PopConfig{ Id="Sigin", Des="签到弹窗", Weight=1000, CloseType=1, },
new PopConfig{ Id="SavePreview", Des="拯救关卡预览", Weight=950, CloseType=0, },
new PopConfig{ Id="RateUs", Des="评价", Weight=950, CloseType=1, },
new PopConfig{ Id="RemoveAds", Des="购买去广告", Weight=1100, CloseType=1, },
new PopConfig{ Id="BuildingGuide", Des="装修引导", Weight=2000, CloseType=1, },
new PopConfig{ Id="LevelGuide", Des="装修完成后关卡引导", Weight=750, CloseType=1, },
new PopConfig{ Id="PlayInterstitialAd", Des="播放广告", Weight=4000, CloseType=1, },
new PopConfig{ Id="EnergyGuide", Des="体力引导", Weight=3000, CloseType=1, },
new PopConfig{ Id="ComeInGameGuide", Des="3-5关弱引导", Weight=960, CloseType=1, },
new PopConfig{ Id="BuildingPop", Des="装修自动弹窗", Weight=900, CloseType=1, },
};
}
弹出管理器:
using Newtonsoft.Json;
using SG.UI;
using SG.Utils;
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//弹出Id,和PopConfig配置表ID一致
public enum PopId
{
Null,
Sigin,
SavePreview,
RateUs,
RemoveAds,
BuildingGuide,
LevelGuide,
PlayInterstitialAd,
EnergyGuide,
ComeInGameGuide,
BuildingPop,
}
[Serializable]
public class PopData
{
public PopId mPopId;
public PopConfig mConf;
//执行弹出
public Action mExePop;
//检测弹出是否结束,如:弹窗是否关闭、引导是否完成、插屏广告是否关闭等
public Func<bool> mCheckIsEnd;
}
public partial class PopManager : MonoSingleton<PopManager>
{
Dictionary<PopId, PopData> mDictPopData= new Dictionary<PopId, PopData>();
//正在执行的弹出序列
[SerializeField]
List<PopData> mPopList = new List<PopData>();
//当前正在执行的弹出
[SerializeField]
PopData mExecutingPopData = null;
[SerializeField]
bool mIsExcuting = false;
protected override void Init()
{
base.Init();
foreach (var item in PopConfig.Datas)
{
var popId = (PopId)Enum.Parse(typeof(PopId), item.Id);
mDictPopData.Add(popId, new PopData {
mPopId = popId,
mConf = item
});
}
mExecutingPopData = null;
}
public void AddPop(PopId popId, Action exePop, Func<bool> checkIsEnd)
{
if (exePop != null && checkIsEnd != null)
{
PopData data;
if (mDictPopData.TryGetValue(popId, out data))
{
data.mExePop = exePop;
data.mCheckIsEnd = checkIsEnd;
mPopList.Add(data);
}
else
{
DebugUtils.LogError("=========>AddPop:" + popId.ToString() + " " + mDictPopData.Count);
}
}
}
public void BeginExecute()
{
mIsExcuting = true;
}
//结束执行弹出逻辑
public void EndExecute()
{
mIsExcuting = false;
foreach (var item in mPopList)
{
item.mCheckIsEnd = null;
item.mExePop = null;
}
mExecutingPopData = null;
mPopList.Clear();
}
//执行弹出逻辑
void Execute()
{
if (mPopList.Count > 0 && mIsExcuting)
{
mPopList.Sort(Sort);
mExecutingPopData = mPopList[0];
DebugUtils.Log("=============>PopManager.Execute:" + mExecutingPopData.mPopId + " " + Time.realtimeSinceStartup);
mPopList.RemoveAt(0);
try
{
UIManager.Instance.LockScreen(0.33f);
mExecutingPopData.mExePop.Invoke();
}
catch (Exception e)
{
DebugUtils.LogError(e.Message + "\n" + e.StackTrace);
}
}
else
{
mExecutingPopData = null;
DebugUtils.Log("========PopManager.Execute: mPopList.Count = 0");
}
}
int Sort(PopData data1, PopData data2)
{
if (data1.mConf.Weight > data2.mConf.Weight)
{
return -1;
}else
{
return 1;
}
}
private void Update()
{
if (mIsExcuting)
{
if (mExecutingPopData != null && mExecutingPopData.mPopId != PopId.Null)
{
if (mExecutingPopData.mCheckIsEnd())
{
if (mExecutingPopData.mConf.CloseType == 1)
{
Execute();
}
else
{
mExecutingPopData = null;
EndExecute();
}
}
}
else
{
if (mPopList.Count > 0)
{
Execute();
}
}
}
}
}