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();
    }
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM