赞
踩
最新:
参考公司lua的mvvm写了一个c#版的,wang-er-s/Framework: a unity mvvm framework, building... (github.com),欢迎提建议
后续会新开一篇文章补充开发思路
------------------------------弃用---------------------------------
之前学了刘国柱老师的UI框架加上我自己的理解做了一个UI框架正好可以使用
这里附上刘国柱老师的博客 http://www.cnblogs.com/LiuGuozhu/ 受益颇深
基本UI框架的类图就是这样了
大体是根据MVC加上我的魔改而成的框架,至少我自己暂时觉得还是思路挺清晰的
Panel的切换是使用的Canvas Group的更改透明度,在加上使用
此方法来更改显示顺序和显隐的
其中的界面反向切换是使用的栈后入先出的特性
反向切换是指一个窗口弹出小窗口后,父窗口的Raycast需要取消,下面贴上核心代码
- using System.Collections;
- using System;
- using System.Collections.Generic;
- using UnityEngine;
- using UnityEngine.UI;
-
- public class UIManager :MonoBehaviour {
-
- /// <summary>
- /// 单例模式:
- /// 1.定义一个静态的对象 在外界访问 内部构造
- /// 2.构造方法私有化
- /// </summary>
- #region 单例模式
-
- private static UIManager _instance;
-
- public static UIManager Instance
- {
- get
- {
- if (_instance == null)
- {
- UIManager[] instances = FindObjectsOfType<UIManager>();
- if (instances != null)
- {
- _instance = instances[0];
- for (var i = 1; i < instances.Length; i++)
- {
- Destroy(instances[i].gameObject);
- }
- }
- }
- return _instance;
- }
- }
-
- #endregion
-
-
- private Transform _canvas;
- public Transform Canvas
- {
- get
- {
- if (_canvas == null)
- _canvas = GameObject.Find("Canvas").transform;
- return _canvas;
- }
- }
- //存储所有面板prefab的地址
- private Dictionary<UIPanelType, string> _DicPanelPath;
- //存储所有实例化的面板身上的BasePanel组件
- private Dictionary<UIPanelType, BasePanel> _DicPanel;
- //存储所有显示的面板上的BasePanel组件
- private Dictionary<UIPanelType, BasePanel> _DicShowPanel;
- //表示显示面板的栈
- private Stack<BasePanel> _StackPanel;
- //全屏显示的节点
- private Transform _TraFullScreen = null;
- //固定显示的节点
- private Transform _TraFixed = null;
- //弹出节点
- private Transform _TraPopUp = null;
- 脚本节点
- //private Transform _TraScript = null;
-
-
- private void Awake()
- {
- ParseUIPanelPathJson();
- _StackPanel = new Stack<BasePanel>();
- _DicPanel = new Dictionary<UIPanelType, BasePanel>();
- _DicShowPanel = new Dictionary<UIPanelType, BasePanel>();
- _TraFullScreen = Canvas.Find("FullScreen");
- _TraFixed = Canvas.Find("Fixed");
- _TraPopUp = Canvas.Find("PopUp");
- DontDestroyOnLoad(Canvas.gameObject);
- //_TraScript = Canvas.Find("Script");
- }
-
-
-
- /// <summary>
- /// 把类型为反向切换的窗体入栈
- /// </summary>
- /// <param name="type"></param>
- private void PushPanel(UIPanelType type)
- {
- BasePanel basePanel = GetPanel(type);
- if (_StackPanel.Count >= 1)
- {
- BasePanel topPanel = _StackPanel.Peek();
- topPanel.OnPause();
- }
- _StackPanel.Push(basePanel);
- basePanel.OnEnter();
- }
-
- /// <summary>
- /// 把类型为反向切换的窗体出栈
- /// </summary>
- /// <param name="type"></param>
- private void PopPanel(UIPanelType type)
- {
- //如果栈里面为空,则返回
- if (_StackPanel.Count <= 0) return;
- BasePanel basePanel = GetPanel(type);
- BasePanel topPanel = _StackPanel.Peek();
- //如果当前要出栈的界面跟栈顶界面相同时 才会出栈
- if(basePanel.gameObject == topPanel.gameObject)
- {
- _StackPanel.Pop();
- topPanel.OnExit();
- //如果出栈后栈里面还有界面则恢复
- if(_StackPanel.Count >= 1)
- {
- _StackPanel.Peek().OnResume();
- }
- }
- else
- {
- Debug.LogError("栈顶界面不是此界面,请检查进出栈!!");
- }
-
- }
-
- /// <summary>
- /// 显示界面
- /// </summary>
- /// <param name="type"></param>
- public void ShowUIForms(UIPanelType type)
- {
- BasePanel basePanel = GetPanel(type);
- switch (basePanel.uiType.uiFormShowMode)
- {
- case UIFormShowMode.Normal:
- EnterUIFormsCache(type);
- break;
- //如果是反切换类型则入栈
- case UIFormShowMode.ReverseChange:
- PushPanel(type);
- break;
- //如果是隐藏其他的类型,清空显示的界面
- case UIFormShowMode.HideOther:
- HideOtherPanel(type);
- break;
- }
- }
-
- /// <summary>
- /// 隐藏界面 如果显示界面字典里面存在此界面
- /// </summary>
- /// <param name="type"></param>
- public void HideUIForms(UIPanelType type)
- {
- BasePanel basePanel = GetPanel(type);
-
- switch (basePanel.uiType.uiFormShowMode)
- {
- case UIFormShowMode.Normal:
- HideUIFormsCache(type);
- break;
- //如果是反切换类型则出栈
- case UIFormShowMode.ReverseChange:
- PopPanel(type);
- break;
- case UIFormShowMode.HideOther:
- HideUIFormsCache(type);
- break;
- }
- }
-
- /// <summary>
- /// 隐藏除此之外的Panel,如果不赋值则清空所有
- /// </summary>
- /// <param name="type"></param>
- public void HideOtherPanel(UIPanelType type = UIPanelType.Null)
- {
- foreach (KeyValuePair<UIPanelType,BasePanel> item in _DicShowPanel)
- {
- item.Value.OnExit();
- }
- _DicShowPanel.Clear();
- if (type != UIPanelType.Null)
- {
- BasePanel basePanel = GetPanel(type);
- basePanel.OnEnter();
- _DicShowPanel.Add(type, GetPanel(type));
- }
-
- }
-
- /// <summary>
- /// 将UI加入到已显示面板的字典中
- /// </summary>
- /// <param name="type"></param>
- private void EnterUIFormsCache(UIPanelType type)
- {
- //如果显示面板字典里面有当前面板则返回
- if (_DicShowPanel.ContainsKey(type)) return;
- BasePanel basePanel = GetPanel(type);
- _DicShowPanel.Add(type, basePanel);
- basePanel.OnEnter();
- }
-
- /// <summary>
- /// 将UI隐藏
- /// </summary>
- /// <param name="type"></param>
- private void HideUIFormsCache(UIPanelType type)
- {
- //如果显示面板字典里面没有当前面板则返回
- if (!_DicShowPanel.ContainsKey(type)) return;
- BasePanel basePanel = GetPanel(type);
- _DicShowPanel.Remove(type);
- basePanel.OnExit();
- }
-
- /// <summary>
- /// 根据面板类型得到实例化的面板
- /// </summary>
- /// <param name="type"></param>
- /// <returns></returns>
- private BasePanel GetPanel(UIPanelType type)
- {
- if (_DicPanel.ContainsKey(type))
- {
- return _DicPanel[type];
- }
- else
- {
- //如果找不到就找这个面板的prefab的路径,然后根据prefab去实例化面板
- BasePanel panel;
- string panelPath = _DicPanelPath.GetValue(type);
- GameObject insGo = GameObject.Instantiate(Resources.Load(panelPath),Canvas) as GameObject;
- insGo.name = type.ToString();
- panel = insGo.GetComponent<BasePanel>();
- switch (panel.uiType.uIFormParentType)
- {
- case UIFormParentType.FUllScreen:
- insGo.transform.SetParent(_TraFullScreen);
- break;
- case UIFormParentType.Fixed:
- insGo.transform.SetParent(_TraFixed);
- break;
- case UIFormParentType.PopUp:
- insGo.transform.SetParent(_TraPopUp);
- break;
- }
- _DicPanel.Add(type, panel);
- return panel;
- }
- }
-
- #region 解析地址json 并存储到字典中
-
- private void ParseUIPanelPathJson()
- {
- TextAsset text = Resources.Load<TextAsset>("UIPanelType");
- JSONObject jSONObject = new JSONObject(text.text);
- if (_DicPanelPath == null)
- _DicPanelPath = new Dictionary<UIPanelType, string>();
- foreach (JSONObject item in jSONObject.list)
- {
- string panelTypeString = item["panelTypeString"].str;
- string path = item["path"].str;
- UIPanelType uIPanelType = (UIPanelType)System.Enum.Parse(typeof(UIPanelType), panelTypeString);
- _DicPanelPath.Add(uIPanelType, path);
- }
- }
-
- #endregion
-
- }

- using System.Collections;
- using System;
- using System.Collections.Generic;
- using UnityEngine;
- using UnityEngine.UI;
-
-
- public class BasePanel : MonoBehaviour {
-
-
- protected CanvasGroup cg;
- public UIType uiType;
-
-
- private void Awake()
- {
- InitData();
- }
-
-
- public virtual void OnCloseBtnClick()
- {
- UIManager.Instance.HideUIForms(uiType.uiPanelType);
- }
-
-
- public virtual void InitData()
- {
- if (cg == null)
- cg = this.gameObject.GetAndAddComponent<CanvasGroup>();
- if (uiType == null)
- uiType = new UIType();
- }
-
-
-
-
- /// <summary>
- /// 界面被显示出来
- /// </summary>
- public virtual void OnEnter()
- {
- cg.alpha = 1;
- cg.blocksRaycasts = true;
- this.gameObject.transform.SetAsLastSibling();
- }
-
-
- /// <summary>
- /// 界面暂停 指的是当其他界面在此界面之上,此界面不是主界面的时候,此界面不接受鼠标检测,如果不需要此功能可以适当更改
- /// </summary>
- public virtual void OnPause()
- {
- cg.blocksRaycasts = false;
- }
-
-
- /// <summary>
- /// 界面继续
- /// </summary>
- public virtual void OnResume()
- {
- cg.blocksRaycasts = true;
- }
-
-
- /// <summary>
- /// 界面不显示,退出这个界面
- /// </summary>
- public virtual void OnExit()
- {
- cg.alpha = 0;
- cg.blocksRaycasts = false;
- }
-
- }

- using System.Collections;
- using System;
- using System.Collections.Generic;
- using UnityEngine;
-
- public class UIType {
-
- /// <summary>
- /// panel类别
- /// </summary>
- public UIPanelType uiPanelType;
- /// <summary>
- /// Panel的显示方式,有正常显示,隐藏其他和反向切换
- /// </summary>
- public UIFormShowMode uiFormShowMode = UIFormShowMode.Normal;
- /// <summary>
- /// 这个透明度暂时没用
- /// </summary>
- public UIFormLucencyType uIFormLucencyType = UIFormLucencyType.Lucency;
- /// <summary>
- /// Panel的父物体类型
- /// </summary>
- public UIFormParentType uIFormParentType = UIFormParentType.PopUp;

代码比较多,不过都有贴心的注释
-------------------------------加了一个代码自动生成的工具-----------------------------------
- using System.Collections;
- using System.Collections.Generic;
- using UnityEngine;
- using System.Threading.Tasks;
- using System;
- using UnityEditor;
- using System.IO;
- using System.Text;
- using UnityEngine.UI;
-
- public class UIElement
- {
- public string Name;
- public string Path;
- public string ComponentName;
- public UIElement(string name,string path,string componentName)
- {
- Name = name;
- Path = path;
- ComponentName = componentName;
- }
-
- public override string ToString()
- {
- string str = string.Format("Name={0} || Path={1} || ComponentName={2}", Name, Path, ComponentName);
- return str;
- }
- }
-
- public class UICodeGenerator
- {
- [MenuItem ( "Assets/CreateCodeDeleteComponent" )]
- public static void CreateCodeDeleteComponent ()
- {
- GetPath ( true );
- }
-
- [MenuItem ( "Assets/OnlyCreateCode" )]
- public static void OnlyCreateCode ()
- {
- GetPath ( false );
- }
-
- public static void GetPath (bool isDeleteComponent)
- {
- var objs =
- Selection.GetFiltered ( typeof ( GameObject ), SelectionMode.Assets | SelectionMode.TopLevel );
- GameObject obj = objs[ 0 ] as GameObject;
- elements = new List<UIElement> ();
- GetPathAs ( obj.transform, isDeleteComponent );
-
- foreach ( var item in elements )
- {
- Debug.Log ( item );
- }
-
- GeneratePane ( "Assets/" + obj.name + ".cs", obj.name, elements );
- GenerateCtrl ( "Assets/" + obj.name + "Ctrl.cs", obj.name, elements );
-
- }
-
- public static List<UIElement> elements;
-
- static void GetPathAs ( Transform transform ,bool isDeleteComponent)
- {
- foreach ( Transform child in transform )
- {
- if ( child.gameObject.GetComponent<UIMark> () )
- {
- elements.Add ( new UIElement ( child.name, GetPath ( child ),
- child.gameObject.GetComponent<UIMark> ().ComponentName ) );
- if ( isDeleteComponent )
- GameObject.DestroyImmediate ( child.gameObject.GetComponent<UIMark> (), true );
- }
-
- if ( child.childCount != 0 )
- {
- GetPathAs ( child, isDeleteComponent );
- }
- }
- }
-
-
- public static void GeneratePane ( string generateFilePath, string behaviourName, List<UIElement> elements )
- {
- var sw = new StreamWriter ( generateFilePath, false, Encoding.UTF8 );
- var strBuilder = new StringBuilder ();
-
- strBuilder.AppendLine ( "using UnityEngine;" );
- strBuilder.AppendLine ( "using UnityEngine.UI;" );
- strBuilder.AppendLine ();
- strBuilder.AppendFormat ( "public class {0} : BasePanel ", behaviourName );
- strBuilder.AppendLine ();
- strBuilder.AppendLine ( "{" );
- foreach ( var item in elements )
- {
- strBuilder.AppendLine ( "\tpublic " + item.ComponentName + " " + item.Name + " { get; private set; }" );
- }
-
- strBuilder.AppendLine ();
- strBuilder.AppendLine ( "\tpublic override void InitData()" );
- strBuilder.AppendLine ( "\t{" );
- foreach ( var item in elements )
- {
- strBuilder.AppendFormat ( "\t\t{0} = transform.Find(\"{1}\").GetComponent<{2}>();", item.Name,
- item.Path.Replace ( behaviourName + "/", "" ), item.ComponentName );
- strBuilder.AppendLine ();
- }
-
- strBuilder.AppendLine ();
- strBuilder.AppendLine ( "\t\tuiType.uIFormParentType = UIFormParentType.PopUp;" );
- strBuilder.AppendLine ( "\t\tuiType.uiFormShowMode = UIFormShowMode.Normal;" );
- strBuilder.AppendLine ( "\t\tuiType.uiPanelType = UIPanelType.BoxPanel;" );
- strBuilder.AppendLine ( "\t}" );
- strBuilder.AppendLine ( "}" );
- sw.Write ( strBuilder );
- sw.Flush ();
- sw.Close ();
-
- AssetDatabase.SaveAssets ();
- AssetDatabase.Refresh ();
- }
-
- public static void GenerateCtrl ( string generateFilePath, string behaviourName , List<UIElement> elements)
- {
- var sw = new StreamWriter ( generateFilePath, false, Encoding.UTF8 );
- var strBuilder = new StringBuilder ();
-
- List<UIElement> temp = new List<UIElement> ();
-
- foreach ( UIElement element in elements )
- {
- if(element.ComponentName.Equals("Button"))
- temp.Add(element);
- }
-
- strBuilder.AppendLine ( "using UnityEngine;" );
- strBuilder.AppendLine ( "using UnityEngine.UI;" );
- strBuilder.AppendLine ();
- strBuilder.AppendFormat ( "public class {0}Ctrl : BaseCtrl ", behaviourName );
- strBuilder.AppendLine ( "{" );
- strBuilder.AppendLine ();
- strBuilder.AppendFormat ( "\tprivate {0} panel;", behaviourName );
- strBuilder.AppendLine ();
- strBuilder.AppendLine ();
- strBuilder.AppendLine ( "\tpublic override void InitPanel()" );
- strBuilder.AppendLine ( "\t{" );
- strBuilder.AppendFormat ( "\t\tpanel = GetComponent<{0}>();", behaviourName );
- strBuilder.AppendLine ();
- foreach ( UIElement element in temp )
- {
- strBuilder.AppendFormat ( "\t\tpanel.{0}.AddListenerGracefully( {1}Click );", element.Name, element.Name );
- strBuilder.AppendLine ();
- }
- strBuilder.AppendLine ( "\t}" );
- strBuilder.AppendLine ();
- foreach ( UIElement element in temp )
- {
- strBuilder.AppendFormat ("\tvoid {0}Click()",element.Name);
- strBuilder.AppendLine ();
- strBuilder.AppendLine ( "\t{" );
- strBuilder.AppendLine ();
- strBuilder.AppendLine ( "\t}" );
- strBuilder.AppendLine ();
- }
-
- strBuilder.AppendLine ( "}" );
- sw.Write ( strBuilder );
- sw.Flush ();
- sw.Close ();
-
- AssetDatabase.SaveAssets ();
- AssetDatabase.Refresh ();
- }
-
- public static string GetPath ( Transform transform )
- {
- var sb = new System.Text.StringBuilder ();
- var t = transform;
- while ( true )
- {
- sb.Insert ( 0, t.name );
- t = t.parent;
- if ( t )
- {
- sb.Insert ( 0, "/" );
- }
- else
- {
- return sb.ToString ();
- }
- }
- }
- }

- using UnityEngine.UI;
- using UnityEngine;
-
- /// <inheritdoc />
- /// <summary>
- /// UI的标记
- /// </summary>
- public class UIMark : MonoBehaviour
- {
- //public UIMarkType MarkType = UIMarkType.DefaultUnityElement;
-
- public Transform Transform
- {
- get { return transform; }
- }
-
- public string CustomComponentName = "";
-
- public virtual string ComponentName
- {
- get
- {
- if ( !string.IsNullOrEmpty ( CustomComponentName ) )
- return CustomComponentName;
- if (null != GetComponent("SkeletonAnimation"))
- return "SkeletonAnimation";
- if (null != GetComponent<ScrollRect>())
- return "ScrollRect";
- if (null != GetComponent<InputField>())
- return "InputField";
- if (null != GetComponent<Text>())
- return "Text";
- if (null != GetComponent("TMP.TextMeshProUGUI"))
- return "TextMeshProUGUI";
- if (null != GetComponent<Button>())
- return "Button";
- if (null != GetComponent<RawImage>())
- return "RawImage";
- if (null != GetComponent<Toggle>())
- return "Toggle";
- if (null != GetComponent<Slider>())
- return "Slider";
- if (null != GetComponent<Scrollbar>())
- return "Scrollbar";
- if (null != GetComponent<Image>())
- return "Image";
- if (null != GetComponent<ToggleGroup>())
- return "ToggleGroup";
- if (null != GetComponent<Animator>())
- return "Animator";
- if (null != GetComponent<Canvas>())
- return "Canvas";
- if (null != GetComponent("Empty4Raycast"))
- return "Empty4Raycast";
- if (null != GetComponent<RectTransform>())
- return "RectTransform";
-
- return "Transform";
-
-
- }
- }
- }

使用方法,把需要使用的组件加上UIMark标记,拖成预设体,右键点击自动生成代码,就会自动生成视图和控制层
-------------------------------弃用-------------------------------------
思想可以借鉴,但是使用起来不是很方便
最新版框架借鉴QFramework,喜欢的可以去看看
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。