一、简介
1.1、UI基类—UIBase
1.2、UI第二层基类,继承自UIBase,分别为UIWindowBase(所有窗口的基类)、UISceneBase(场景UI基类)
继承自UISceneBase的类都放在UIRoot物体上,而继承自UIWindowBase的类,主要放在窗口上,例如整个登
录注册面板的父物体UIPanel物体之上,类似的。
1.3、三个基本的管理器:LayerUIMgr(UI层级管理器)、SceneUIMgr(场景管UI理器)、WindowUIMgr(窗口
UI管理器)
SceneUIMgr(场景管UI理器):主要用于场景UI加载,即场景UIRoot预制物体的加载。
WindowUIMgr(窗口UI管理器):主要用于例如登录窗口、注册窗口等的预制加载,关闭和销毁。
LayerUIMgr(UI层级管理器):记录一个当前最大深度值,用于设置传入物体的深度层级值。
二、代码
2.1、UIBase
using UnityEngine;
/// <summary>
/// UI基类
/// </summary>
public class UIBase : MonoBehaviour
{
private void Awake()
{
OnAwake();
}
void Start()
{
#region 给所有的UIButton绑定事件
UIButton[] btnArr = GetComponentsInChildren<UIButton>(true);//setactive为false的也要获得
for (int i = 0; i < btnArr.Length; i++)
{
UIEventListener.Get(btnArr[i].gameObject).onClick += BtnClick;
}
#endregion
OnStart();
}
private void OnDestroy()
{
BeforeOnDestory();
}
private void BtnClick(GameObject go)
{
OnBtnClick(go);
}
protected virtual void OnAwake()
{
}
protected virtual void OnStart()
{
}
protected virtual void OnBtnClick(GameObject go)
{
}
protected virtual void BeforeOnDestory()
{
}
}
2.2、UIWindowBase(所有窗口的基类)以及UISceneBase(场景UI基类)
2.2.1、UIWindowBase
using UnityEngine;
/// <summary>
/// 所有窗口的基类
/// </summary>
public class UIWindowBase : UIBase
{
/// <summary>
/// 挂点类型,挂在哪个容器位置下
/// </summary>
public WindowUIContainerType containerType = WindowUIContainerType.Center;
/// <summary>
/// 显示类型
/// </summary>
public WindowShowStyle showStyle = WindowShowStyle.Normal;
/// <summary>
/// 打开或者关闭动画效果持续时间
/// </summary>
public float duration = 0.2f;
/// <summary>
/// 当前窗口类型
/// </summary>
[HideInInspector]
public WindowUIType CurrentUIType;
/// <summary>
/// 下一个要打开的窗口
/// </summary>
public WindowUIType m_NextOpenWindow = WindowUIType.None;
/// <summary>
/// 关闭当前自己
/// </summary>
protected virtual void Close()
{
WindowUIMgr.Instance.CloseWindow(CurrentUIType);
}
/// <summary>
/// 销毁自身之前调用
/// </summary>
protected override void BeforeOnDestory()
{
if (m_NextOpenWindow == WindowUIType.None) return;
WindowUIMgr.Instance.OpenWindow(m_NextOpenWindow);
}
}
2.2.2、UISceneBase(场景UI基类)
using UnityEngine;
/// <summary>
/// 场景UI基类
/// </summary>
public class UISceneBase : UIBase
{
/// <summary>
/// 容器_居中
/// </summary>
public Transform Container_Center;
}
2.2.3、例举一些继承自这两个类的一些实现
2.2.3.1、UISceneLogonCtrl 挂载在Scene_LogOn场景的UIRoot物体上。用于显示进入场景就加载打开登录窗口
using System.Collections;
using UnityEngine;
public class UISceneLogonCtrl : UISceneBase
{
protected override void OnStart()
{
base.OnStart();
//加载登录窗口
StartCoroutine(OpenLogOnWindow());
}
private IEnumerator OpenLogOnWindow()
{
yield return new WaitForSeconds(0.5f);
GameObject obj = WindowUIMgr.Instance.OpenWindow(WindowUIType.LogOn);
}
private void Update()
{
}
}
2.2.3.2、UI_PanelLogonCtrl 挂在在登录窗口面板最外层父物体上
using UnityEngine;
/// <summary>
/// 登录窗口UI控制器
/// </summary>
public class UI_PanelLogonCtrl : UIWindowBase
{
/// <summary>
/// 昵称
/// </summary>
[SerializeField]
private UIInput m_InputNockName;
/// <summary>
/// 密码
/// </summary>
[SerializeField]
private UIInput m_InputPwd;
/// <summary>
/// 提示
/// </summary>
[SerializeField]
private UILabel m_libTip;
#region OnBtnClick 重写基类OnBtnClick
/// <summary>
/// 重写基类OnBtnClick
/// </summary>
/// <param name="go"></param>
protected override void OnBtnClick(GameObject go)
{
Debug.Log("登录窗口Btn调用");
switch (go.name)
{
case "BtnLog":
BtnLogOn();
break;
case "BtnReg":
BtnReg();
break;
}
}
#endregion
/// <summary>
/// 我要注册按钮
/// </summary>
void BtnReg()
{
//this.Close();
//m_NextOpenWindow = WindowUIType.Reg;
WindowUIMgr.Instance.OpenWindow(WindowUIType.Reg);
}
/// <summary>
/// 登录按钮
/// </summary>
void BtnLogOn()
{
string nickName = this.m_InputNockName.value.Trim();
string pwd = m_InputPwd.value.Trim();
string oldNickName = PlayerPrefs.GetString(GlobalInit.MMO_NICKNAME);
string oldPwd = PlayerPrefs.GetString(GlobalInit.MMO_PWD);
if (nickName == string.Empty || pwd == string.Empty)
{
m_libTip.text = "密码或者昵称不能为空";
return;
}
if (oldNickName != nickName || oldPwd != pwd)
{
m_libTip.text = "您输入的账号或者密码错误";
return;
}
GlobalInit.Instance.CurrRoleNickName = nickName;
SceneMgr.Instance.LoadToCity();
}
}
2.3管理类 WindowUIMgr(窗口管理类)、LayerUIMgr(UI层级管理器)、SceneUIMgr(场景管UI理器)
2.3.1、WindowUIMgr
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 窗口UI管理器,窗口加载等方法
/// </summary>
public class WindowUIMgr : Singleton<WindowUIMgr>
{
/// <summary>
/// 当前场景中的窗口存贮表
/// </summary>
private Dictionary<WindowUIType, UIWindowBase> m_DicWindow = new Dictionary<WindowUIType, UIWindowBase>();
public int OpenWindowCount
{
get
{
return m_DicWindow.Count;
}
}
#region LoadWindow 打开窗口
/// <summary>
/// 打开窗口,窗口命名书写为Panel+枚举类型名=预制体的名称
/// </summary>
/// <param name="type">窗口类型</param>
public GameObject OpenWindow(WindowUIType type)
{
if (type == WindowUIType.None) return null;
GameObject obj = null;
if (!m_DicWindow.ContainsKey(type))
{
//枚举名要与预制体一致
obj = ResourcesMgr.Instance.Load(ResourcesMgr.ResourcesType.UIWindows, string.Format("Panel{0}", type.ToString()), true);
if (obj == null) return null;
UIWindowBase windowbase = obj.GetComponent<UIWindowBase>();
if (windowbase == null) return null;
windowbase.CurrentUIType = type;
m_DicWindow.Add(type, windowbase);
Transform transParent = null;
switch (windowbase.containerType)
{
case WindowUIContainerType.Center:
Debug.Log("????");
transParent = SceneUIMgr.Instance.CurrentUIScene.Container_Center;
break;
case WindowUIContainerType.TL: break;
case WindowUIContainerType.TR: break;
case WindowUIContainerType.BL: break;
case WindowUIContainerType.BR: break;
}
obj.transform.parent = transParent;
obj.transform.localPosition = Vector3.zero;
obj.transform.localScale = Vector3.one;
NGUITools.SetActive(obj, false);
StartShowWindow(windowbase, true);
}
else
{
obj = m_DicWindow[type].gameObject;
}
LayerUIMgr.Instance.SetLayer(obj);
return obj;
}
#endregion
#region 开始打开窗口
private void StartShowWindow(UIWindowBase windowbase, bool isOpen)
{
switch (windowbase.showStyle)
{
case WindowShowStyle.Normal:
ShowNormal(windowbase, isOpen);
break;
case WindowShowStyle.CenterToBig:
ShowCenterToBig(windowbase, isOpen);
break;
case WindowShowStyle.FromDown:
ShowFromDir(windowbase, 1, isOpen);
break;
case WindowShowStyle.FromLeft:
ShowFromDir(windowbase, 2, isOpen);
break;
case WindowShowStyle.FromRight:
ShowFromDir(windowbase, 3, isOpen);
break;
case WindowShowStyle.FromTop:
ShowFromDir(windowbase, 0, isOpen);
break;
}
}
#endregion
#region 关闭窗口
/// <summary>
/// 关闭窗口
/// </summary>
/// <param name="windowbase"></param>
public void CloseWindow(WindowUIType type)
{
if (m_DicWindow.ContainsKey(type))
{
StartShowWindow(m_DicWindow[type], false);
}
}
#endregion
#region 各种打开效果
private void ShowNormal(UIWindowBase windowbase, bool isOpen)
{
if (isOpen)
{
NGUITools.SetActive(windowbase.gameObject, true);
}
else
{
DestroyWindow(windowbase);
}
}
/// <summary>
/// 从中间变大
/// </summary>
/// <param name="obj"></param>
/// <param name="isOpen"></param>
private void ShowCenterToBig(UIWindowBase windowbase, bool isOpen)
{
TweenScale ts = windowbase.gameObject.GetOrCreatComponent<TweenScale>();
ts.animationCurve = GlobalInit.Instance.UIAnimationCurve;
ts.from = Vector3.zero;//开始大小
ts.to = Vector3.one;//结束大小
ts.duration = windowbase.duration;//持续时间
ts.SetOnFinished(() =>//动画完成之后调用事件
{
if (!isOpen)
{
DestroyWindow(windowbase);
}
});
NGUITools.SetActive(windowbase.gameObject, true);
if (!isOpen) ts.Play(isOpen);//如果isOpen=false,即我想要关闭窗口,动画运行反方向
}
/// <summary>
/// 从不同的方向加载
/// </summary>
/// <param name="windowbase"></param>
/// <param name="dirType">0--从上往下,1-从下往上,2--从左向右,3---从右到左</param>
/// <param name="isOpen"></param>
private void ShowFromDir(UIWindowBase windowbase, int dirType, bool isOpen)
{
TweenPosition tp = windowbase.gameObject.GetOrCreatComponent<TweenPosition>();
tp.animationCurve = GlobalInit.Instance.UIAnimationCurve;
Vector3 from = Vector3.zero;
switch (dirType)
{
case 0:
from = new Vector3(0, 1000, 0);
break;
case 1:
from = new Vector3(0, -1000, 0);
break;
case 2:
from = new Vector3(-1000, 0, 0);
break;
case 3:
from = new Vector3(1000, 0, 0);
break;
}
tp.from = from;//开始大小
tp.to = Vector3.one;//结束大小
tp.duration = windowbase.duration;//持续时间
tp.SetOnFinished(() =>//动画完成之后调用事件
{
if (!isOpen)
{
DestroyWindow(windowbase);
}
});
NGUITools.SetActive(windowbase.gameObject, true);
if (!isOpen) tp.Play(isOpen);//如果isOpen=false,即我想要关闭窗口,动画运行反方向
}
#endregion
#region 销毁窗口
/// <summary>
/// 销毁窗口
/// </summary>
/// <param name="obj"></param>
private void DestroyWindow(UIWindowBase windowbase)
{
m_DicWindow.Remove(windowbase.CurrentUIType);
GameObject.Destroy(windowbase.gameObject);
LayerUIMgr.Instance.CheckOpenWindow();
}
#endregion
}
2.3.2、SceneUIMgr
using UnityEngine;
using System.Collections;
/// <summary>
/// 场景管UI理器
/// </summary>
public class SceneUIMgr : Singleton <SceneUIMgr>
{
public UISceneBase CurrentUIScene;
#region LoadSceneUI 加载场景UI
/// <summary>
/// 加载场景UI
/// </summary>
/// <param name="type"></param>
/// <returns></returns>
public GameObject LoadSceneUI(SceneUIType type)
{
GameObject obj = null;
switch (type )
{
case SceneUIType.LogOn:
obj = ResourcesMgr.Instance.Load(ResourcesMgr.ResourcesType.UIScene, GameConst.UIRoot_LogOnScene);
CurrentUIScene = obj.GetComponent<UISceneLogonCtrl>();
break;
case SceneUIType.Loading:break;
case SceneUIType.MainCity:
obj = ResourcesMgr.Instance.Load(ResourcesMgr.ResourcesType.UIScene, GameConst.UIRoot_CityScene);
CurrentUIScene = obj.GetComponent<UISceneCityCtrl>();
break;
}
return obj ;
}
#endregion
}
2.3.3、LayerUIMgr
using UnityEngine;
using System.Collections;
/// <summary>
/// UI层级管理器
/// </summary>
public class LayerUIMgr : Singleton <LayerUIMgr> {
/// <summary>
/// UIPanel层级深度
/// </summary>
private int m_UIPanelDepth = 50;
public void Reset()
{
m_UIPanelDepth = 50;
}
/// <summary>
/// 检查窗口数量,如果没有打开的窗口,重置深度
/// </summary>
public void CheckOpenWindow()
{
if(WindowUIMgr.Instance .OpenWindowCount==0)
{
Reset();
}
}
public void SetLayer(GameObject obj)
{
m_UIPanelDepth += 1;
UIPanel[] panArr = obj.GetComponentsInChildren<UIPanel>();
if(panArr .Length >0)
{
for (int i = 0; i < panArr .Length ; i++)
{
panArr[i].depth += m_UIPanelDepth;
}
}
}
}
2.4、思路
每个场景有一个场景管理类,如Scene_LogOn场景具有一个类LogOnSceneCtrl.cs类,进入场景就加载场景UI的UIRoot物体。而每个UIRoot上面都挂载一个UISceneBase的子类,该子类中可以在加载时的start方法里加载一些马上显示的窗口之类的。
using UnityEngine;
using System.Collections;
public class LogOnSceneCtrl : MonoBehaviour {
private void Awake()
{
SceneUIMgr.Instance.LoadSceneUI(SceneUIType.LogOn);
}
}
2.5、其他类
2.5.1、单例类
using UnityEngine;
using System.Collections;
using System;
public class Singleton<T>:IDisposable where T:new ()
{
private static T instance;
public static T Instance
{
get
{
if(instance ==null )
{
instance = new T();
}
return instance;
}
}
public virtual void Dispose()
{
}
}
2.5.2、枚举类
#region WindowUIType 窗口类型
/// <summary>
/// 窗口类型
/// </summary>
public enum WindowUIType
{
/// <summary>
/// 未设置
/// </summary>
None,
/// <summary>
/// 登录窗口
/// </summary>
LogOn,
/// <summary>
/// 注册窗口
/// </summary>
Reg,
/// <summary>
/// 角色信息窗口
/// </summary>
RoleInfo,
}
#endregion
#region WindowShowStyle 窗口打开方式
/// <summary>
/// 窗口打开方式
/// </summary>
public enum WindowShowStyle
{
/// <summary>
/// 正常打开
/// </summary>
Normal,
/// <summary>
/// 从中间放大
/// </summary>
CenterToBig,
/// <summary>
/// 从上往下
/// </summary>
FromTop,
/// <summary>
/// 从下往上
/// </summary>
FromDown,
/// <summary>
/// 从左往右
/// </summary>
FromLeft,
/// <summary>
/// 从右向左
/// </summary>
FromRight,
}
#endregion
#region WindowUIContainerType UI容器类型
/// <summary>
/// UI容器类型
/// </summary>
public enum WindowUIContainerType
{
/// <summary>
/// 左上
/// </summary>
TL,
//右上
TR,
/// <summary>
/// 左下
/// </summary>
BL,
/// <summary>
/// 右下
/// </summary>
BR,
/// <summary>
/// 居中
/// </summary>
Center,
}
#endregion
#region SceneUIType 场景UI类型
/// <summary>
/// 场景UI类型
/// </summary>
public enum SceneUIType
{
/// <summary>
/// 登录
/// </summary>
LogOn,
/// <summary>
/// 加载
/// </summary>
Loading,
/// <summary>
/// 主城
/// </summary>
MainCity,
}
#endregion
#region 场景类型
/// <summary>
/// 场景类型
/// </summary>
public enum SceneType
{
LogOn,
City,
}
#endregion
#region 角色类型
/// <summary>
/// 角色类型
/// </summary>
public enum RoleType
{
/// <summary>
/// 未设置
/// </summary>
None = 0,
/// <summary>
/// 当前玩家
/// </summary>
MainPlayer = 1,
/// <summary>
/// 怪
/// </summary>
Monster = 2
}
#endregion
#region 角色状态
/// <summary>
/// 角色状态
/// </summary>
public enum RoleState
{
/// <summary>
/// 未设置
/// </summary>
None = 0,
/// <summary>
/// 待机
/// </summary>
Idle = 1,
/// <summary>
/// 跑
/// </summary>
Run = 2,
/// <summary>
/// 攻击
/// </summary>
Attack = 3,
/// <summary>
/// 受伤
/// </summary>
Hurt = 4,
/// <summary>
/// 死亡
/// </summary>
Die = 5,
}
#endregion
#region 角色动画名称
/// <summary>
/// 角色动画名称
/// </summary>
public enum RoleAnimatorName
{
Idle_Normal,
Idle_Fight,
Run,
Hurt,
Die,
PhyAttack1,
PhyAttack2,
PhyAttack3
}
#endregion
/// <summary>
/// 动画切换参数变量名
/// </summary>
public enum ToAnimatorCondition
{
ToIdleNormal,
ToIdleFight,
ToRun,
ToHurt,
ToDie,
ToPhyAttack,
CurrState,
}