UI框架
UI框架的含义
含义:UI框架用于管理场景中所有的面板,负责控制面板之间的跳转
UI框架的意义
1、随着游戏系统的复杂化,UI控件越来越多,各个UI之间的直接通讯,已经UI与GameObject之间的关系会越来越复杂 2、代码耦合性会很强
UI框架的实例
1、框架面板的设计
MainMenuPanel:主菜单面板 BagPanel:背包面板 ItemMessagePanel:物品信息面板 ShopPanel:商城面板 SkillPanel:技能面板 SystemPanel:系统面板 TaskPanel:技能面板
我们将设计好的面板做成预制体,放在Resources的目录下。
2、Json数据的读取
UIPanelInfo.json
{
"infoList":
[
{
"panelTypeString": "ItemMessage",
"path": "UIPanel/ItemMessagePanel"
},
{
"panelTypeString": "BagPanel",
"path": "UIPanel/BagPanel"
},
{
"panelTypeString": "MainMenu",
"path": "UIPanel/MainMenuPanel"
},
{
"panelTypeString": "Shop",
"path": "UIPanel/ShopPanel"
},
{
"panelTypeString": "Skill",
"path": "UIPanel/SkillPanel"
},
{
"panelTypeString": "System",
"path": "UIPanel/SystemPanel"
},
{
"panelTypeString": "Task",
"path": "UIPanel/TaskPanel"
}
]
}
将所有信息作为一个infolist类的对象
UIPanelType
public enum UIPanelType
{
BagPanel,
ItemMessage,
MainMenu,
Shop,
Skill,
System,
Task,
}
UIManager
public class UIManager
{
private Dictionary<UIPanelType, string> panelPathDicr;
private UIManager()
{
ParseUIPanelTypeJson();
}
private static UIManager instance;
public static UIManager GetInstance()
{
if (instance == null)
{
instance = new UIManager();
}
return instance;
}
[Serializable]
class UIPanelTypeJson
{
public List<UIPanelInfo> infoList;
}
private void ParseUIPanelTypeJson()
{
panelPathDicr = new Dictionary<UIPanelType, string>();
TextAsset ta = Resources.Load<TextAsset>("UIPanelType");
UIPanelTypeJson jsonObject = JsonUtility.FromJson<UIPanelTypeJson>(ta.text);
foreach (UIPanelInfo info in jsonObject.infoList)
{
panelPathDicr.Add(info.panelType, info.path);
}
}
public void Test()
{
string path;
panelPathDicr.TryGetValue(UIPanelType.Shop, out path);
Debug.Log(path);
}
}
UIPanelInfo
[Serializable]
public class UIPanelInfo:ISerializationCallbackReceiver
{
[NonSerialized]
public UIPanelType panelType;
public string panelTypeString;
public string path;
public void OnAfterDeserialize()
{
UIPanelType type = (UIPanelType)System.Enum.Parse(typeof(UIPanelType), panelTypeString);
panelType = type;
}
public void OnBeforeSerialize()
{
}
}
分析:
首先
1、UIPanelType类
作为一个枚举类,用于记录各个面板,保存面板的类型
2、UIPanelType.json
这是一个Json文件,用于存储各个面板的具体信息
例如:
"panelTypeString": "MainMenu",
"path": "UIPanel/MainMenuPanel"
panelTypeString保存对象
path保存路径
3、UIPanelInfo
负责与Json文件向对应
public UIPanelType panelType;
public string path;
这里要将其设置为可序列化的状态[Serializable],让这个类可以读盘与写盘,方便后期对信息进行修改
,也可以避免直接修改Json文件
4、UIManger
是UI框架的核心,负责管理各种框架
第一步,将其设置为单例模式
第二步,将Json文件解析
第三步,使用UIPanelInfo的数组来接受Json文件的信息
第四步,遍历UIPanelInfo数组,并将其中的数据加入字典当中
其中有两个关键点。
第一,加载Json文件,并将文件解析为UIPanelInfo对象的数组
第二,遍历数组,并加入字典中,方便以后对其数据进行各种操作
3、框架逻辑设计
BasePanel的设计
public class BasePanel : MonoBehaviour
{
public virtual void OnEnter()
{ }
public virtual void OnPause()
{ }
public virtual void OnResume()
{ }
public virtual void OnExit()
{ }
}
BagPanel继承BasePanel
public class BagPanel:BasePanel
{
private CanvasGroup canvasGroup;
private void Start()
{
if (canvasGroup == null)
{
canvasGroup = GetComponent<CanvasGroup>();
}
}
public override void OnExit()
{
canvasGroup.blocksRaycasts = false;
transform.DOLocalMoveX(600, 0.5f).OnComplete(() => canvasGroup.alpha = 0);
}
public void OnClosePanel()
{
UIManager.GetInstance().PopPanel();
}
public override void OnEnter()
{
if (canvasGroup == null)
{
canvasGroup = GetComponent<CanvasGroup>();
}
canvasGroup.alpha = 1;
canvasGroup.blocksRaycasts = true;
Vector3 temp = transform.localPosition;
temp.x = 600;
transform.localPosition = temp;
transform.DOLocalMoveX(0, 0.5f);
}
public override void OnPause()
{
canvasGroup.blocksRaycasts = false;
}
public override void OnResume()
{
canvasGroup.blocksRaycasts = true;
}
public void OnItemButtonClick()
{
UIManager.GetInstance().PushPanel(UIPanelType.ItemMessage);
}
}
完善后的UIManager
public class UIManager
{
private Transform canvasTransform;
private Transform CanvasTransform
{
get
{
if (canvasTransform == null)
{
canvasTransform = GameObject.Find("Canvas").transform;
}
return canvasTransform;
}
}
private Dictionary<UIPanelType, string> panelPathDicr;
private Dictionary<UIPanelType, BasePanel> panelDict;
private Stack<BasePanel> panelStacks;
public void PushPanel(UIPanelType panelType)
{
if (panelStacks == null)
{
panelStacks = new Stack<BasePanel>();
}
if (panelStacks.Count > 0)
{
BasePanel topPanel = panelStacks.Peek();
topPanel.OnPause();
}
BasePanel panel = GetPanel(panelType);
panel.OnEnter();
panelStacks.Push(panel);
}
public void PopPanel()
{
if (panelStacks == null)
{
panelStacks = new Stack<BasePanel>();
}
if (panelStacks.Count <= 0)
{
return;
}
BasePanel topPanel = panelStacks.Pop();
topPanel.OnExit();
if (panelStacks.Count <= 0) return;
BasePanel topPanel2 = panelStacks.Peek();
topPanel2.OnResume();
}
public BasePanel GetPanel(UIPanelType panelType)
{
if (panelDict == null)
{
panelDict = new Dictionary<UIPanelType, BasePanel>();
}
BasePanel panel = panelDict.TryGet(panelType);
if (panel == null)
{
string path = panelPathDicr.TryGet(panelType);
var pan = Resources.Load(path);
GameObject instPanel = GameObject.Instantiate(pan) as GameObject;
instPanel.transform.SetParent(CanvasTransform, false);
panelDict.Add(panelType, instPanel.GetComponent<BasePanel>());
return instPanel.GetComponent<BasePanel>();
}
else
{
return panel;
}
}
private UIManager()
{
ParseUIPanelTypeJson();
}
private static UIManager instance;
public static UIManager GetInstance()
{
if (instance == null)
{
instance = new UIManager();
}
return instance;
}
[Serializable]
class UIPanelTypeJson
{
public List<UIPanelInfo> infoList;
}
private void ParseUIPanelTypeJson()
{
panelPathDicr = new Dictionary<UIPanelType, string>();
TextAsset ta = Resources.Load<TextAsset>("UIPanelType");
UIPanelTypeJson jsonObject = JsonUtility.FromJson<UIPanelTypeJson>(ta.text);
foreach (UIPanelInfo info in jsonObject.infoList)
{
panelPathDicr.Add(info.panelType, info.path);
}
}
public void Test()
{
string path;
panelPathDicr.TryGetValue(UIPanelType.Shop, out path);
Debug.Log(path);
}
}
分析
1、BasePanel作为基类被其他的具体类继承
而BasePanel中的方法为
OnEnter()——进入
OnPause()——暂停
OnResume()——恢复
OnExit()——退出
2、具体的类在继承的基础上,进行具体的修改,添加事件
3、UIManager则负责使用“栈”来对不同页面进行管理
|