Loading

Unity3D-UI框架

Monday, February 21 2022

Tasks

Notes

创建了UI框架和场景框架

UI Framework

其中包括Base,Concrete,Manager,UITool和UIType

Base

含有BasePanel脚本,是所有UI面板的父类,包含UI面板的状态信息。

BasePanel

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

/// <summary>
/// 所有UI面板的父类,包含UI面板的状态信息
/// </summary>
public class BasePanel
{
    /// <summary>
    /// UI信息
    /// </summary>
   public UIType UIType { get; private set; }

    /// <summary>
    /// UI管理工具
    /// </summary>
   public UITool UITool { get; private set; }

    /// <summary>
    /// 面板管理器
    /// </summary>
    public PanelManager PanelManager { get; private set; }

    /// <summary>
    /// UI管理器
    /// </summary>
    public UIManager UIManager { get; private set; }

    #region Initialize

    /// <summary>
    /// 初始化
    /// </summary>
    /// <param name="uIType"></param>
    public BasePanel(UIType uIType) {
        UIType = uIType;
    }

    /// <summary>
    /// 初始化UITool
    /// </summary>
    /// <param name=""></param>
    public void Initialize(UITool tool) {
        UITool = tool;
    }

    /// <summary>
    /// 初始化面板管理器
    /// </summary>
    /// <param name="manager"></param>
    public void Initialize(PanelManager manager) {
        PanelManager = manager;
    }

    /// <summary>
    /// 初始化UI管理器
    /// </summary>
    /// <param name="manager"></param>
    public void Initialize(UIManager manager) { 
        UIManager = manager;
    }

    #endregion

    /// <summary>
    /// UI进入时执行的操作,只会执行一次
    /// </summary>
    public virtual void OnEnter() { }

    /// <summary>
    /// UI暂停时执行的操作
    /// </summary>
    public virtual void OnPause() { }

    /// <summary>
    /// UI继续时执行的操作
    /// </summary>
    public virtual void OnResume() { }

    /// <summary>
    /// UI退出时的操作
    /// </summary>
    public virtual void OnExit() { }

    /// <summary>
    /// 显示一个面板
    /// </summary>
    /// <param name="panel"></param>
    public void Push(BasePanel panel) => PanelManager?.Push(panel);

    /// <summary>
    /// 弹出一个面板
    /// </summary>
    /// <param name="panel"></param>
    public void Pop(BasePanel panel) => PanelManager?.Pop();
}

Concrete

存储面板的脚本

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class StartPanel : BasePanel
{
    //面板的地址
    static readonly string path = "Prefab/Star";
    //载入面板
    public StartPanel() : base(new UIType(path)) { }

    public override void OnEnter() {
        //进入时添加的功能
    }
}

Manager

包括PanelManager,UIManager。

PanelManager

PanelManager是面板管理,使用栈来存储UI

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

/// <summary>
/// 面板管理器,用栈来存储UI
/// </summary>
public class PanelManager
{
    /// <summary>
    /// 存储UI面板的栈
    /// </summary>
    private Stack<BasePanel> stackPanel;

    /// <summary>
    /// UI管理器
    /// </summary>
    private UIManager uIManager;
    private BasePanel panel;

    /// <summary>
    /// 初始化
    /// </summary>
    public PanelManager() {
        stackPanel = new Stack<BasePanel>();
        uIManager = new UIManager();
    }

    /// <summary>
    /// 执行面板入栈操作,此操作会显示一个面板
    /// </summary>
    /// <param name="nextpanel">要显示的面板</param>
    public void Push(BasePanel nextpanel) { 
        if(stackPanel.Count > 0) {
            panel = stackPanel.Peek();
            panel.OnPause();
        }
        stackPanel.Push(nextpanel);
        GameObject panelGo = uIManager.GetSingleUI(nextpanel.UIType);
        nextpanel.Initialize(new UITool(panelGo));
        nextpanel.Initialize(this);
        nextpanel.Initialize(uIManager);
        nextpanel.OnEnter();
    }

    /// <summary>
    /// 执行面板出栈操作,此操作会执行面板的OnExit方法
    /// </summary>
    public void Pop() {
        if (stackPanel.Count > 0) { 
            stackPanel.Pop().OnExit();
        }
        if(stackPanel.Count > 0) {
            stackPanel.Peek().OnResume();
        }
    }

    /// <summary>
    /// 清除所有面板
    /// </summary>
    public void PopAll() {
        while (stackPanel.Count > 0) {
            stackPanel.Pop().OnExit();
        }
    }
}

UIManager

UIManager存储所有的UI信息,并进行创建或者销毁

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

/// <summary>
/// 储存所有UI信息,并可以创建或者销毁
/// </summary>
public class UIManager
{
    /// <summary>
    /// 储存所有UI信息的字典,每一个UI信息都会对应一个GameObject
    /// </summary>
    private Dictionary<UIType, GameObject> dicUI;

    public UIManager() {
        dicUI = new Dictionary<UIType,GameObject>();
    }

    /// <summary>
    /// <para>获取一个UI对象</para>
    /// </summary>
    /// <param name="type">UI信息</param>
    /// <returns></returns>
    public GameObject GetSingleUI(UIType type) {
        GameObject parent = GameObject.Find("Canvas");
        if (parent == null) {
            Debug.LogWarning("Canvas不存在,请仔细查找有无这个对象");
            return null;
        }

        if (dicUI.ContainsKey(type))
            return dicUI[type];

        GameObject ui = GameObject.Instantiate(Resources.Load<GameObject>(type.Path), parent.transform);
        ui.name = type.Name;
        dicUI.Add(type, ui);
        return ui;
    }

    /// <summary>
    /// 销毁一个UI对象
    /// </summary>
    /// <param name="type">UI信息</param>
    public void DestroyUI(UIType type) {
        if (dicUI.ContainsKey(type)) {
            GameObject.Destroy(dicUI[type]);
            dicUI.Remove(type);
        }
    }
}

UITool

UITool是UI的管理工具,可以获取某个和添加某个子对象

using System.Collections;
using System.Collections.Generic;
using UnityEngine;


/// <summary>
/// UI的管理工具,包括获取某个子对象组件
/// </summary>
public class UITool
{
    /// <summary>
    /// 当前活动面板
    /// </summary>
    GameObject activePanel;

    /// <summary>
    /// 构造函数
    /// </summary>
    /// <param name="panel"></param>
    public UITool(GameObject panel) {
        activePanel = panel;
    }

    /// <summary>
    /// 给当前活动页面获取或添加一个组件
    /// </summary>
    /// <typeparam name="T">组件类型</typeparam>
    /// <returns>组件</returns>
    public T GetOrAddComponent<T>() where T : Component {
        if (activePanel.GetComponent<T>() == null) {
            activePanel.AddComponent<T>();
        }
        return activePanel.GetComponent<T>();
    }

    /// <summary>
    /// 根据名称查找子对象
    /// </summary>
    /// <param name="name">子对象名称</param>
    /// <returns>子对象</returns>
    public GameObject FindChildGameObject(string name) { 
        Transform[] Trans = activePanel.GetComponentsInChildren<Transform>();

        foreach (var item in Trans) {
            if(item.name == name) {
                return item.gameObject;
            }
        }

        Debug.LogWarning($"{activePanel.name}未找到{name}的相关组件!!!");
        return null;
    }

    /// <summary>
    /// 根据名称查找或添加子对象组件
    /// </summary>
    /// <typeparam name="T">组件类型</typeparam>
    /// <param name="name">组件名字</param>
    /// <returns>组件,多个同名返回第一个</returns>
    public T GetOrAddComponentInChildren<T>(string name) where T : Component { 
        GameObject child = FindChildGameObject(name);
        if (child != null) { 
            if(child.GetComponent<T>() == null) {
                child.AddComponent<T>();
            }

            return child.GetComponent<T>();
        }

        Debug.LogWarning($"未获取到{name}组件");
        return null;
    }
}

UIType

UI的数据

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

/// <summary>
/// UI数据
/// </summary>
public class UIType 
{
    /// <summary>
    /// UI名字
    /// </summary>
    public string Name { get; private set; }
    
    /// <summary>
    /// UI地址
    /// </summary>
    public string Path { get; private set; }

    public UIType(string path) {
        Path = path;
        Name = path.Substring(path.LastIndexOf('/') + 1);
    }

}

Scenes

其中包括Base,Concrete和SceneSystem

Base

其中包括SceneState脚本,为抽象类

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

/// <summary>
/// 场景状态
/// </summary>
public abstract class SceneState
{
    /// <summary>
    /// 场景进入
    /// </summary>
    public abstract void OnEnter();

    /// <summary>
    /// 场景退出
    /// </summary>
    public abstract void OnExit();
}

Concrete

为场景脚本加载场景时的操作和退出时的操作

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;

/// <summary>
/// 开始场景
/// </summary>
public class StarScene : SceneState
{
    /// <summary>
    /// 场景名称
    /// </summary>
    readonly string sceneName = "Star 1";
    PanelManager panelManager;

    public override void OnEnter() {
        panelManager = new PanelManager();
        if(SceneManager.GetActiveScene().name != sceneName) {
            SceneManager.LoadScene(sceneName);
            SceneManager.sceneLoaded += SceneLoaded;
        }
        else {
            panelManager.Push(new StartPanel());
        }
    }

    public override void OnExit() {
        SceneManager.sceneLoaded -= SceneLoaded; 
        panelManager.PopAll();
    }

    /// <summary>
    /// 场景加载完毕之后执行的方法
    /// </summary>
    /// <param name="scene"></param>
    /// <param name="load"></param>
    private void SceneLoaded(Scene scene,LoadSceneMode load) {
        panelManager.Push(new StartPanel());
        Debug.Log($"{sceneName}加载完毕!");
    }
}

SceneSystem

这个为场景的状态管理系统,来判断是否进入当前场景

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

/// <summary>
/// 场景的状态管理系统
/// </summary>
public class SceneSystem
{
    /// <summary>
    /// 场景状态类
    /// </summary>
    SceneState sceneState;

    /// <summary>
    /// 设置当前场景并进入当前场景
    /// </summary>
    /// <param name="state"></param>
    public void SetScene(SceneState state) {
        //if(sceneState != null) {
        //    sceneState.OnExit();
        //}
        //sceneState = state;
        //if (sceneState != null) { 
        //    sceneState.OnEnter();
        //}
         
        sceneState?.OnExit();
        sceneState = state;
        sceneState?.OnEnter();
    }
}
posted @ 2022-02-21 16:17  数学天才琪露诺  阅读(686)  评论(3编辑  收藏  举报