小游戏UI框架用起来也比较方便。做UI时,首先要有个大致框架,大致的UI方向,一般需要把UI的弹窗分为两种,一种是layer,一种是dlg,layer是主层级面板,一般用于主界面,游戏界面等,dlg是二级弹窗,一般用于设置,排行等弹窗界面。UI需要一个管理类UIMgr统一管理这两种分类。
UIMgr一般是单例类,那么我们就需要一个统一的全局单例类管理它,让其他需要单例的可以直接继承使用。
以下是一个继承MonoBehavior的单例类MonoSingleton。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// Mono singleton.
/// 单实例设计模式、保证整个游戏过程中只有一个实例
/// </summary>
public class MonoSingleton<T> : MonoBehaviour where T: MonoBehaviour {
[SerializeField]
bool _isDestory = false;
public static T Instance;
public virtual void Awake () {
Instance = this as T;
if (!_isDestory) {
DontDestroyOnLoad(gameObject);
}
}
public virtual void OnDestory() {
Instance = null;
}
}
然后就是继承他的UIMgr了。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class UIMgr : MonoSingleton<UIMgr> {
[SerializeField]
Transform _layerRoot;
[SerializeField]
Transform _dlgRoot;
Dictionary<Enums.LayerId, BaseLayer> _layers = new Dictionary<Enums.LayerId, BaseLayer>();
Dictionary<Enums.DlgId, BaseDlg> _dlgs = new Dictionary<Enums.DlgId, BaseDlg>();
BaseLayer _showLayer = null;
[HideInInspector]
public Vector2 size; //实际的屏幕宽高
public override void Awake () {
base.Awake();
size = GetComponent<RectTransform>().sizeDelta;
}
private void Start () {
LoadUI();
}
void LoadUI () {
foreach (var layer in _layerRoot.GetComponentsInChildren<BaseLayer>(true)) {
if (!_layers.ContainsKey(layer.id)) {
if (layer.id == Enums.LayerId.LayerSplash) {
_showLayer = layer;
layer.gameObject.SetActive(true);
} else {
layer.gameObject.SetActive(false);
}
_layers.Add(layer.id, layer);
}
}
foreach (var dlg in _dlgRoot.GetComponentsInChildren<BaseDlg>(true)) {
if (!_dlgs.ContainsKey(dlg.id)) {
dlg.gameObject.SetActive(false);
_dlgs.Add(dlg.id, dlg);
}
}
var layerPrefabs = Resources.LoadAll<GameObject>("Prefabs/UIs/Layers");
foreach (var prefab in layerPrefabs) {
Enums.LayerId id = prefab.GetComponent<BaseLayer>().id;
if (!_layers.ContainsKey(id)) {
var layer = Instantiate(prefab, _layerRoot).GetComponent<BaseLayer>();
layer.gameObject.SetActive(false);
layer.transform.localScale = Vector3.one;
_layers.Add(id, layer);
}
}
var dlgPrefabs = Resources.LoadAll<GameObject>("Prefabs/UIs/Dlgs");
foreach (var prefab in dlgPrefabs) {
Enums.DlgId id = prefab.GetComponent<BaseDlg>().id;
if (!_dlgs.ContainsKey(id)) {
var dlg = Instantiate(prefab, _dlgRoot).GetComponent<BaseDlg>();
dlg.gameObject.SetActive(false);
dlg.transform.localScale = Vector3.one;
_dlgs.Add(id, dlg);
}
}
}
public void ShowLayer (Enums.LayerId id, params object[] objs) {
Debug.Log("ShowLayer0");
if (_showLayer != null && _showLayer.id == id)
{
Debug.Log("ShowLayer1");
_showLayer.OnShow();
return;
}
if (_showLayer != null) {
_showLayer.OnHide();
}
//Debug.Log(_showLayer);
if (_layers.ContainsKey(id)) {
_showLayer = _layers[id];
_showLayer.OnShow(objs);
} else {
Debug.Log("can't find layer:" + id);
}
}
public void ShowDlg(Enums.DlgId id, params object[] objs) {
if (_dlgs.ContainsKey(id))
{
_dlgs[id].OnShow(objs);
}
else {
Debug.Log("can't find dlg:" + id);
}
}
public BaseLayer GetLayer(Enums.LayerId id) {
if (_layers.ContainsKey(id))
{
return _layers[id];
}
else {
return null;
}
}
public BaseDlg GetDlg(Enums.DlgId id)
{
if (_dlgs.ContainsKey(id))
{
return _dlgs[id];
}
else
{
return null;
}
}
}
最后需要两个基类让layer和dlg分别继承。
baselayer如下
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BaseLayer : MonoBehaviour {
public Enums.LayerId id;
protected Animator animator;
protected Coroutine animCoroutine = null;
protected object _params;
protected virtual void Awake() {
animator = GetComponent<Animator>();
}
protected virtual void Start() {
}
public virtual void OnShow(params object[] objs) {
_params = objs;
gameObject.SetActive(true);
if (animator != null)
{
animator.Play("Show");
}
}
public virtual void OnRefresh() {
}
public virtual void OnHide() {
if (animator != null)
{
animator.Play("Hide");
}
else {
gameObject.SetActive(false);
}
}
public void OnAnimListener(string animName) {
if (animName == "Hide")
{
gameObject.SetActive(false);
}
}
}
下面的是basedlg
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BaseDlg : MonoBehaviour {
public Enums.DlgId id;
protected object _params;
public virtual void OnShow (object objs) {
_params = objs;
gameObject.SetActive(true);
}
public virtual void OnHide () {
gameObject.SetActive(false);
}
public virtual void OnRefresh()
{
}
}
这样用起来很方便,能拿到每个layer和dlg,便于管理和扩展