本人水平有限 如有不足还请斧正,本文仅作学习交流使用不做任何商业用途

        经过很多天的学习,我也算是拥有了自己的一套工具,该文章内容是向Unity_Joker老师学习总结得来,吃水不忘打井人,不胜感激        

JKFrame2.0独立游戏开发框架使用课程 | Unity 中文课堂

Joker-YF/JKFrame: Indie Game Framework

        QFrameWork暂时放一放 等我独立完成一些东西以后再分析源码

         我目前还看不懂,我想实战一些东西再回来搞框架层面的东西,毕竟他们都只是工具,不然拿着金锄头锄shi然后长出来一大堆食人花,到头来还是反噬自己

        仅展示部分关键代码,因为是开源框架所以大家可以自行查看

        多说无益 可以直接看视频Unity JKF 1.0UI小框架 留存记录_哔哩哔哩_bilibili

目录

1.UIManager

主要成员

核心功能

UILayer 关键方法

        2.UI特性

        3.UI基类

        4.使用测试

1.UIManager

主要成员

  • UILayer 类:管理每层 UI,含 panelRootmaskImage 和窗口计数 count
  • uILayers 数组:存储所有 UI 层级信息。
  • UIElementDic 字典:存 UI 窗口元数据。
  • uITips 对象:用于显示提示。

核心功能

  1. 窗口显示Show 方法根据传入类型和层级显示窗口,若未实例化则从预制体创建,更新层级并调用 UILayer.PanelOnShow 调整遮罩。
  2. 窗口关闭Close 方法按类型关闭窗口,依缓存策略隐藏或销毁,调用 UILayer.PanelOnClose 更新遮罩。
  3. 全部关闭CloseAll 方法遍历关闭所有窗口。
  4. 提示添加AddTips 方法添加提示信息到 uITips

UILayer 关键方法

  • PanelOnShow:显示窗口时增加计数并更新遮罩。
  • PanelOnClose:关闭窗口时减少计数并更新遮罩。
  • Update_UI:调整遮罩位置和射线检测状态。
namespace JKFrameWork
{
    using System;
    using System.Collections.Generic;
    using UnityEngine;
    using UnityEngine.UI;

    public class UI_Manager : ManagerBase<UI_Manager>
    {
        [Serializable]
        private class UILayer
        {
            public Transform panelRoot;
            public Image maskImage;
            private int count = 0; //该层窗口数量

            /// <summary>
            /// 更新层级之中的活动窗口和遮罩位置
            /// </summary>
            public void PanelOnShow()
            {
                count += 1;
                Update_UI();
            }
            public void PanelOnClose()
            {
                count -= 1;
                Update_UI();
            }
            /// <summary>
            /// 主要是调整Mask的位置
            /// </summary>
            public void Update_UI()
            {
                //调整遮罩位置 永远在当前活动窗口的倒数第二个
                int maskIndex = panelRoot.childCount - 2;
                //如果位置超出界限 就放在最上面
                maskImage.transform.SetSiblingIndex(maskIndex < 0 ? 0 : maskIndex);
                //raycastTarget打开遮罩
                maskImage.raycastTarget = count != 0;
            }
        }

        [SerializeField]
        private UILayer[] uILayers;

        #region Tips
        [SerializeField]
        private UITips uITips;
        public void AddTips(string info)
        {
            uITips.AddTips(info);
        }
        #endregion


        public Dictionary<Type, UI_Element> UIElementDic { get { return GameRoot.Instance.GameSetting.UIElementDict; } }

        /// <summary>
        /// 显示窗口
        /// </summary>
        /// <typeparam name="T">窗口类型</typeparam>
        /// <param name="layer">层级 -1等于不设置</param>
        public T Show<T>(int layer = -1) where T : UI_WindowBase
        {
            return Show(typeof(T), layer) as T;
        }
        public UI_WindowBase Show(Type type, int layer = -1)
        {

            if (UIElementDic.ContainsKey(type))
            {
                UI_Element uiElement = UIElementDic[type];
                //如果层级为-1 说明需要设置一下层级
                int layerNum = layer == -1 ? uiElement.layerNum : layer;

                //实例化 或者 创建出来
                if (uiElement.objInstance != null)
                {
                    uiElement.objInstance.gameObject.SetActive(true);
                    uiElement.objInstance.transform.SetParent(uILayers[layerNum].panelRoot);
                    //递进层
                    uiElement.objInstance.transform.SetAsLastSibling();
                    uiElement.objInstance.OnShow();
                }
                else
                {
                    UI_WindowBase window = ResManager.InstantiateForPrefab(uiElement.prefab, uILayers[layerNum].panelRoot).GetComponent<UI_WindowBase>();
                    uiElement.objInstance = window;
                    window.InitWindow();
                    window.OnShow();
                }

                uiElement.layerNum = layerNum;
                uILayers[layerNum].PanelOnShow();
                return uiElement.objInstance;
            }
            return null;
        }

        public void Close<T>()
        {
            Close(typeof(T));
        }

        public void Close(Type type)
        {
            if (UIElementDic.ContainsKey(type))
            {
                var uiElement = UIElementDic[type];

                if (uiElement.objInstance == null) return;

                // 缓存则隐藏
                if (uiElement.isCache)
                {
                    //如果关闭就放在最上方 让其被挡住
                    uiElement.objInstance.transform.SetAsFirstSibling();
                    uiElement.objInstance.gameObject.SetActive(false);
                }
                // 不缓存则销毁
                else
                {
                    Destroy(uiElement.objInstance);
                    uiElement.objInstance = null;
                }
                uILayers[uiElement.layerNum].PanelOnClose();
            }
         
        }

        /// <summary>
        /// 关闭全部窗口
        /// </summary>
        public void CloseAll()
        {
            // 处理缓存中所有状态的逻辑
            var enumerator = UIElementDic.GetEnumerator();
            while (enumerator.MoveNext())
            {
                enumerator.Current.Value.objInstance.Close();
            }
        }
    }

}

        2.UI特性

namespace JKFrameWork
{
    using Sirenix.OdinInspector;
    using System;

    /// <summary>
    /// UI元素的特性
    /// 每个UI窗口都应该添加
    /// </summary>
    [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
    public class UIElementAttribute : Attribute
    {
        public bool isCache;
        public string resPath;
        public int layerNum;

        public UIElementAttribute(bool isCache, string resPath, int layerNum)
        {
            this.isCache = isCache;
            this.resPath = resPath;
            this.layerNum = layerNum;

        }
    }
}
namespace JKFrameWork
{
    using Sirenix.OdinInspector;
    using UnityEngine;

    public class UI_Element
    {
        [LabelText("是否需要缓存")]
        public bool isCache;
        [LabelText("预制体")]
        public GameObject prefab;
        [LabelText("UI层级")]
        public int layerNum;
        /// <summary>
        /// 这个元素的窗口对象
        /// </summary>
        [HideInInspector]
        public UI_WindowBase objInstance;
    }

}

        3.UI基类

namespace JKFrameWork
{
    using System;
    using UnityEngine;
    /// <summary>
    /// 窗口结果
    /// </summary>
    public enum WindowReslut
    {
        None,
        Yes,
        No
    }

    public class UI_WindowBase : MonoBehaviour
    {
        public Type windowType { get { return this.GetType(); } }

        public virtual void InitWindow() { }

        public virtual void OnShow() { }

        /// <summary>
        /// 默认会执行关闭
        /// </summary>
        public virtual void OnCloseClick<T>() { UI_Manager.Instance.Close<T>(); Close(); }

        /// <summary>
        /// 默认会执行关闭
        /// </summary>
        public virtual void OnYesClick<T>() { UI_Manager.Instance.Close<T>(); Close(); }

        /// <summary>
        /// 取消事件
        /// </summary>
        public virtual void Close()
        {
            CancelEvent();
        }


        #region 事件管理
        protected virtual void RegisterEvent()
        {
            EventManager.AddEventListener("UpdateLanguage", OnUpdateLanguage);
        }
        protected virtual void CancelEvent()
        {
            EventManager.RemoveListener("UpdateLanguage", OnUpdateLanguage);
        }
        protected virtual void OnUpdateLanguage() { }

        #endregion
    }

}

        4.使用测试

using JKFrameWork;
using UnityEngine;

public class UIManager : MonoBehaviour
{
    // Start is called once before the first execution of Update after the MonoBehaviour is created
    void Start()
    {
        UI_Manager.Instance.Show<TestA>();
        UI_Manager.Instance.Show<TestB>();
        UI_Manager.Instance.Show<TestC>();
      
    }

    // Update is called once per frame
    void Update()
    {
        if (Input.GetKeyDown(KeyCode.A)) {
            UI_Manager.Instance.Show<TestA>();
        }
        if (Input.GetKeyDown(KeyCode.B))
        {
            UI_Manager.Instance.Show<TestB>();
        }
        if (Input.GetKeyDown(KeyCode.C))
        {
            UI_Manager.Instance.Show<TestC>();
        }
    }
}
using UnityEngine;
using JKFrameWork;
using UnityEngine.UI;

[UIElement(true, "UI/PanelA",0 )]
public class TestA : UI_WindowBase
{
    public override void InitWindow()
    {
     
        this.GetComponentInChildren<Button>().onClick.AddListener(OnCloseClick<TestA>);
    }

    public override void OnCloseClick<T>()
    {
        base.OnCloseClick<T>();
    }

    public override void OnShow()
    {
        Debug.Log("A触发了 显示了B的功能");
     
    }

}
using JKFrameWork;
using UnityEngine;
using UnityEngine.UI;


[UIElement(true, "UI/PanelB", 0)]
public class TestB : UI_WindowBase
{
    public override void InitWindow()
    {
        base.InitWindow();
        this.GetComponentInChildren<Button>().onClick.AddListener(OnCloseClick<TestB>);
    }
    public override void OnShow()
    {

        base.OnShow();
    }

    public override void OnCloseClick<T>()
    {
        base.OnCloseClick<T>();
    }
}
using JKFrameWork;
using UnityEngine;
using UnityEngine.UI;
[UIElement(true, "UI/PanelC",0)]
public class TestC : UI_WindowBase
{
    public override void InitWindow()
    {
        base.InitWindow();
        this.GetComponentInChildren<Button>().onClick.AddListener(OnCloseClick<TestC>);
    }

    public override void OnShow()
    {
        base.OnShow();
    }
    public override void OnCloseClick<T>()
    {
        base.OnCloseClick<T>();
        Debug.Log("关闭了C窗口");
    }
}

Logo

分享前沿Unity技术干货和开发经验,精彩的Unity活动和社区相关信息

更多推荐