UI框架学习记录(UGUI)

当游戏里的界面多了之后,如果没有管理的话是很很不方便的,因此我在网上查找资料学习之后,写了一个简单版本的UI框架。目前功能很基础,后续会慢慢更新

点击按钮可以打开对应的界面,并暂停所有其他界面(不可以交互),当关闭当前的界面后,上一个被打开的界面会恢复暂停状态(可以被交互)且可以按顺序回到上个界面,如打开界面的顺序为ABCD,从D开始关闭界面会依次打开CBA界面
一共有如下几个类
在这里插入图片描述
从面板基类开始,这里界面分为:进入事件,暂停事件,恢复事件,退出事件,还有关闭事件,包括一个初始化的方法。这里是用了canvasgroup来控制界面的显示和隐藏。代码如下

public class BasePanel : MonoBehaviour
{
    private CanvasGroup canvasGroup;
    private Button closeBtn;

    private void Awake()
    {
        Init();
    }

    private void Init()
    {
        canvasGroup = this.GetComponent<CanvasGroup>();
        if (canvasGroup == null) canvasGroup = gameObject.AddComponent<CanvasGroup>();


        Transform btn = this.transform.Find("Close");
        if (btn!=null)
        {
            closeBtn= btn.GetComponent<Button>();
            closeBtn.onClick.AddListener(Close);
        }
       
    }

    /// <summary>
    /// 进入面板
    /// </summary>
    public virtual void OnEnter()
    {
        canvasGroup.alpha = 1;
        canvasGroup.blocksRaycasts = true;

    }
    /// <summary>
    /// 暂停面板
    /// </summary>
    public virtual void OnPause()
    {
        canvasGroup.alpha = 1;
        canvasGroup.blocksRaycasts = false;
    }
    /// <summary>
    /// 恢复暂停
    /// </summary>
    public virtual void OnResume()
    {
        canvasGroup.alpha = 1;
        canvasGroup.blocksRaycasts = true;
    }
    /// <summary>
    /// 退出面板
    /// </summary>
    public virtual void  OnExit()
    {
        canvasGroup.alpha = 0;
        canvasGroup.blocksRaycasts = false;
    }
    /// <summary>
    /// 关闭按钮
    /// </summary>
    public void Close()
    {
        UIManager.Manager.PopPanel();
    }

}

然后是2个UI信息类

public class UIPanel
{
    public UIPanelType uiPanelType;//界面类型
    public string uiPanelPath;//界面路径

    public UIPanel()
    { }
    public UIPanel(string path, UIPanelType type)
    {
        uiPanelPath = path;
        uiPanelType = type;
    }
}
public enum UIPanelType
{
    MainMenuPanel,
    SystemSettingPanel,
    StorePanel,
    SecondPanel,

}

最后是核心管理类,这里用了栈进行存储操作,并把此类做成了单例

public class UIManager
{
    /// <summary>
    /// 预制体路径
    /// </summary>
    readonly string panelPreafabPath = Application.dataPath + @"/Resources/UIPanelPrefab";
    /// <summary>
    /// json文件路径
    /// </summary>
    readonly string jsonPath = Application.dataPath + @"/Json/UIJson.json";

    /// <summary>
    /// UIManager单例
    /// </summary>
    private static UIManager manager;
    public static UIManager Manager
    {
        get
        {
            if (manager == null)manager = new UIManager();
                   
            return manager;
        }
    }

    /// <summary>
    /// 场景中的Canvas
    /// </summary>
    private Transform canvasTransform;
    public Transform CanvasTransform
    {
        get
        {
            if (canvasTransform==null)canvasTransform = GameObject.Find("Canvas").transform;

            return canvasTransform;
        }
    }
    /// <summary>
    /// 存储所有panel
    /// </summary>
    private List<UIPanel> panelList;
    /// <summary>
    /// 存储所有BasePanel
    /// </summary>
    private Dictionary<UIPanelType, BasePanel> panelDic;
    /// <summary>
    /// 存储当前正在展示的界面
    /// </summary>
    private Stack<BasePanel> panelStack;
    

    private UIManager()
    {
        SaveUIPanelInfoToJson();
    }

    /// <summary>
    /// 根据路径读取json文件并返回list
    /// </summary>
    /// <param name="jsonPath">json路径</param>
    /// <returns></returns>
    public List<UIPanel> ReadJsonFile(string jsonPath)
    {
        if (!File.Exists(jsonPath)) File.WriteAllText(jsonPath, "[]");

        List<UIPanel> list = JsonMapper.ToObject<List<UIPanel>>(File.ReadAllText(jsonPath));
        
        return list;
        
    }

    /// <summary>
    /// 根据路径写入json到本地文件
    /// </summary>
    /// <param name="jsonPath">json路径</param>
    /// <param name="panels">list对象</param>
    public void WriteJsonFile(string jsonPath,List<UIPanel> panels)
    {
        string json = JsonMapper.ToJson(panels);
        File.WriteAllText(jsonPath,json);
    }

    /// <summary>
    /// 根据预制体写入json到本地
    /// </summary>
    public void SaveUIPanelInfoToJson()
    {
        panelList = ReadJsonFile(jsonPath);

        //读取文件夹信息
        DirectoryInfo folder = new DirectoryInfo(panelPreafabPath);

        foreach (FileInfo file in folder.GetFiles("*.prefab"))
        {
            //获取panel类型
            UIPanelType type = (UIPanelType)Enum.Parse(typeof(UIPanelType), file.Name.Replace(".prefab", ""));
            //组合path拿到路径
            string path= @"UIPanelPrefab/" + file.Name.Replace(".prefab", "");
            //判断是否查找成功
            bool UIPanelISInList = false;

            UIPanel uiPanel = panelList.SearchPanelForType(type);

            if (uiPanel!=null)//如果有就更新一下luj
            {
                uiPanel.uiPanelPath = path;
                UIPanelISInList = true;
            }

            if (!UIPanelISInList)//如果没有就新建一个并加入list
            {
                UIPanel panel = new UIPanel(path, type);
                panelList.Add(panel);
            }
        }
        WriteJsonFile(jsonPath, panelList);
        AssetDatabase.Refresh();
    }
    /// <summary>
    /// 获取对应的界面
    /// </summary>
    /// <param name="type">界面的类型</param>
    /// <returns></returns>
    public BasePanel GetPanel(UIPanelType type)
    {
        if (panelDic==null)panelDic = new Dictionary<UIPanelType, BasePanel>();

        BasePanel panel = panelDic.TryGetValue(type);

        if (panel==null)
        {
            string path = panelList.SearchPanelForType(type).uiPanelPath;

            if (path==null)
                throw new Exception("查无此UIPanelType的Prefab");
            if (Resources.Load(path) == null)
                throw new Exception("无法找到该路径下的prefab");

            GameObject instPanel = GameObject.Instantiate(Resources.Load(path)) as GameObject;

            instPanel.transform.SetParent(CanvasTransform, false);

            panelDic.Add(type, instPanel.GetComponent<BasePanel>());

            return instPanel.GetComponent<BasePanel>();

        }
        return panel;
    }
    /// <summary>
    /// 界面入栈
    /// </summary>
    /// <param name="type"></param>
    public void PushPanel(UIPanelType type)
    {
        if (panelStack==null)panelStack = new Stack<BasePanel>();

        if (panelStack.Count>0)
        {
            BasePanel topPanel = panelStack.Peek();
            topPanel.OnPause();
        }

        BasePanel panel = GetPanel(type);
        panelStack.Push(panel);
        panel.OnEnter();
    }

    /// <summary>
    /// 界面出栈
    /// </summary>
    public void PopPanel()
    {
        if (panelStack == null) panelStack = new Stack<BasePanel>();

        if (panelStack.Count <= 0) return;

        BasePanel topPanel = panelStack.Pop();
        topPanel.OnExit();

        if (panelStack.Count <= 0) return;
        BasePanel topPanel2 = panelStack.Peek();
        topPanel2.OnResume();
    }
}

最后2个拓展方法
在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值