Unity 从零开始的框架搭建1-5 关于JKF里面的UI小框架
本人水平有限 如有不足还请斧正,本文仅作学习交流使用不做任何商业用途经过很多天的学习,我也算是拥有了自己的一套工具,该文章内容是向Unity_Joker老师学习总结得来,吃水不忘打井人,不胜感激QFrameWork暂时放一放 等我独立完成一些东西以后再分析源码我目前还看不懂,我想实战一些东西再回来搞框架层面的东西,毕竟他们都只是工具,不然拿着金锄头锄shi然后长出来一大堆食人花,到头来还是反噬自己
·
本人水平有限 如有不足还请斧正,本文仅作学习交流使用不做任何商业用途
经过很多天的学习,我也算是拥有了自己的一套工具,该文章内容是向Unity_Joker老师学习总结得来,吃水不忘打井人,不胜感激
QFrameWork暂时放一放 等我独立完成一些东西以后再分析源码
我目前还看不懂,我想实战一些东西再回来搞框架层面的东西,毕竟他们都只是工具,不然拿着金锄头锄shi然后长出来一大堆食人花,到头来还是反噬自己
仅展示部分关键代码,因为是开源框架所以大家可以自行查看
多说无益 可以直接看视频Unity JKF 1.0UI小框架 留存记录_哔哩哔哩_bilibili
目录
1.UIManager
主要成员
UILayer
类:管理每层 UI,含panelRoot
、maskImage
和窗口计数count
。uILayers
数组:存储所有 UI 层级信息。UIElementDic
字典:存 UI 窗口元数据。uITips
对象:用于显示提示。
核心功能
- 窗口显示:
Show
方法根据传入类型和层级显示窗口,若未实例化则从预制体创建,更新层级并调用UILayer.PanelOnShow
调整遮罩。 - 窗口关闭:
Close
方法按类型关闭窗口,依缓存策略隐藏或销毁,调用UILayer.PanelOnClose
更新遮罩。 - 全部关闭:
CloseAll
方法遍历关闭所有窗口。 - 提示添加:
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窗口");
}
}
更多推荐
所有评论(0)