UGUI
文章目录
1.六大基础组件概述
六大基础组件有哪些:
Canvas对象上依附的:
- 1.
Canvas
:画布,用于渲染UI控件 - 2.
Canvas Scaler
:画布分辨率自适应 - 3.
Graphic Raycaster
:射线事件交互 - 4.
RectTransform
:UI对象位置锚点控制,控制位置和对齐方式
EventSystem对象上依附的: - 5.
EventSystem
:玩家输入事件响应 - 6.
Standalone Input Module
:独立输入模块
UGUI是Unity引擎自带的GUI系统,对初学者十分重要,让我们一起来学习UGUI吧。
1.1 Canvas组件
作用:画布。其子对象渲染的根本。
重点知识:
- 1.场景中可以存在多个canvas,分别管理各自UI的显示参数
Render Mode参数解析;
- 1.
Screen Space - Overlay
:覆盖模式,UI始终在前。
– a.Pixel Perfect
:是否开启无锯齿精确渲染(性能换效果)
– b.Sort Order
:渲染顺序,越后渲染图层越上。
– c.Target Display
:目标显示屏幕。 - 2.
Screen Space - Camera
:摄像机模式,3D物体显示在UI之前。
– a.Render Camera
:用于渲染UI的摄像机(不建议设置主摄像机)
– b.Plane Distance
:UI在平面距离摄像机的距离。
一般情况下,单独独立出一个摄像机管理UI。 - 3.
World Space
:世界空间,3D模式。主要用于VR,AR。
一般情况下,该模式下可以关联主摄像机。
1.2 CanvasScaler组件
作用:在不同分辨率下UI控件大小的自适应。不负责位置!位置由之后的RectTransform组件控制。
屏幕分辨率:
屏幕分辨率 = 画布尺寸 * 缩放系数
参考分辨率Reference Resolution:
在缩放模式的宽高模式中出现的参数,参与分辨率自适应计算。
分辨率大小自适应:
通过一定的算法 以 屏幕分辨率 和 参考分辨率 参与计算得出 缩放系数,该结果会影响所有UI控制的缩放大小。
UI Scale Mode参数解析:
- 1.
Constant Pixel Size
:恒定像素模式,UI大小始终不变。
– a.图片的尺寸计算:UI原始尺寸 = 图片大小(像素) / (Pixels Per Unit / Reference Pixels Per Unit)
- 2.
Scale With Screen Size
:”缩放模式,根据屏幕尺寸进行缩放。
– a.Expand
:水平或垂直拓展画布区域,可能有黑边。最大程度的缩小UI元素,保证都能装下所有UI。该模式下一般会比参考分辨率大,以便展示UI的全部细节。
– b.Shrink
:水平或垂直收缩画布区域,可以有裁剪。最大程度的方法UI元素,该模式下一般会比参考分辨率小,以便使画面填满屏幕。
– c.Match Width Or Height
:用于只有横屏(match = 1)或竖屏模式(match = 0)的游戏。 - 3.
Constant Physical Size
:恒定物理模式,UI元素始终保持相同物理大小。 - 4.
3D模式
:当Scale中设为World Space
时。该组件中自动变为 World模式,即为3D模式。
– a.Dynamic Pixels Per Unit
:UI中动态创建的位图中,单位像素数(密度)。适当增大该值可以使其上UI组件显示更清晰。
1.3 Graphic Raycaster组件
作用:图形射线投射器,检测UI输入事件的涉嫌发射器,负责通过射线检测玩家和UI元素的交互,判断是否点击到了UI元素。
参数解析:
- 1.
Ignore Reversed Graphics
:是否忽略反转图型 - 2.
Blocking Objects
:射线被哪些类型的碰撞器阻挡(覆盖渲染下无效) - 3.
Blocking Mask
:射线被哪些层级的碰撞器阻挡(覆盖模式下无效)
1.4 Event System组件
作用:事件系统,管理玩家输入事件分发给各UI组件。所有UI事件都通过该组件中轮询检测并做相应的执行。
参数解析:
- 1.
First Selected
:首先选择的游戏对象 - 2.
Send Navigation Events
:是否允许导航事件(键盘移动选择) - 3.
Drag Threshold
:拖拽阈值,移动多少像素算拖拽
1.5 Standalone Input Module组件
作用:独立输入模块
参数解析:
该模块一般不做修改,默认值即可,用于关联Input Manager配合接收用户输入。
1.6 RectTransform组件
作用:专门用来管理UI的位置大小相关组件,在Transform的基础上(继承)加入了矩形相关,引入了中心点,锚点,长宽等属性。
参数解析:
- 1
Pivot
:轴心点位置,旋转绕轴心点。 - 2.
Anchors
:相对于父矩形锚点。max和min取值范围都为0~1。 - 3.
Pos(X,Y,Z)
:轴心点相对锚点的位置 - 4.
Width/Height
:宽高 - 5.
Left/Top/Right/Button
:矩形边相对于锚点的位置 - 6.
Blueprint Mode
:蓝图模式,编辑旋转和缩放不会影响矩形 - 7.
Raw Edit Mode
:原始编辑模式,改变轴心和锚点值不会改变矩形位置 - 8.快捷设置锚点轴心点以及UI位置(左上)。
2.三大基础控件概述
2.1 图像控件Image
参数解析:
- 1.
Source Image
:必须是“精灵Sprite”类型。 - 2.
Image Type
:
– a.Simple
:普通模式,均匀缩放整个图片
– b.Sliced
:切片模式,只拉伸九宫格中间的区域,防止其余部分被拉伸变形。
–c.Tiled
:平铺模式,会重复最基础的图像操作重复填充中央部分
– d.Filled
:填充模式,扇形,圆形,条形填充,适合做血条或经验条… - 3.
Use Sprite Mesh
:使用精灵网格 - 4.
Preserve Aspect
:确保图像保持现有尺寸 - 5.
Set Native Size
:设置图片资源原始大小
2.2 文本控件Text
参数解析:
- 1.
Line Spacing
:行之间的垂直间距 - 2.
Horizontal Overflow
– a.Wrap
:包裹模式,字体始终在举行范围内,超出后自动换行
– b.Overflow
:溢出模式,字体可以溢出矩形框 - 3.
Vertical Overflow
:同理。 - 4.富文本写法:(注意勾选rich text)
- 5.给文字加边缘线或阴影:
给字体加上Outline或者Shadow组件。
2.3 RawImage原始图像组件
与Image区别:主要用于显示大图(背景图),不需要打入图集的图片,网络下载图片等等。
3.七大组合控件
3.1 Button组件
参数解析:
- 1.
Interaction
:是否开启按钮交互 - 2.
Trasition
:
– a.None
:无任何点击状态改变
– b.Color Tint
:不同状态的切换有颜色反馈
– c.Sprite Swap
:不同状态的切换有图片反馈
– d.Animation
:不同状态的切换有动画反馈 - 3.··Navigation``:导航功能(键盘操作选中按钮)
按钮事件添加:
可拖入脚本对象但不建议,按钮繁多时浪费时间,建议采用代码的方式加入监听事件。
//获取到按钮组件btn
btn.onClick.AddListener(ClickBtn);
//事件方法
private void ClickBtn()
{
print("按钮点击,通过代码的方式");
}
//也可以通过匿名函数或Lambda表达式
btn.onClick.AddListener(() => {...})
补充:做UI之前必须先修改Canvas上的内容并且创建一个父类型的画板,改为自适应多类型屏幕大小,否则后期不好改!!!
3.2 Toggle组件
概念:开关对象,处理玩家单选框以及多选框的关键组件。
参数详解:
- 1.
Is On
:当前的选中状态 - 2.
Graphic
:选中时显示的图片 - 3.
Group
:单选框分组实现:
– a.将单选框分组挂载在父对象上,将其一组的单选框关联即可。
– b.具体操作流程:创建一个父对象ToggleGroup,添加Toggle Group组件。将父节点拖入Toggle中的Group即可。 - 4.
Allow Switch off
:允许不选择任何一个单选框
选项框事件与按钮事件类似,此处不多做赘述,关注如果使用带参数事件函数,需要注意在拖入选择时选择动态参数的函数,不是静态!
3.3 InputField组件
参数详解:
- 1.
Content Type
:输入类型限制
2.其他参数:
3.4 Slider滑动条组件
参数解析:
3.5 ScrollBar滚动条组件
参数解析:
3.6 ScrollView滚动视图组件
参数解析:
补充:如果不需要进度条的显示,可以手动删除进度条对象,但一定注意在原对象中将其关联的属性滞空,并调整内容大小以致较舒适的范畴。
代码应用:
//获取组件
ScrollRect sr = this.GetComponent<ScrollRect>();
//设置相对位置
sr.normalizedPosition = new Vector2(0, 0.5f);
3.7 DropDown下拉列表组件
参数详解:
4.图集
Q:为什么要打图集?
A:目的是减少DC(DrawCall),提高性能。
Q:什么是DC?
A:DC是CPU通知GPU进行一次渲染的命令,如果DC次数较多会导致游戏卡顿,我们可以通过打图集,将小图合成大图,将本应n次DC变成1次来提高性能。
Unity中打图集操作的使用:
- 1.开启打图集功能方式:
Edit ---> Project Setting ---> Editor ---> Sprite Packer
- 2.在资源中新建一个图集
SpriteAtlas
,UI中建议取消勾选Allow Rotation
和Tight Packing
。并加入图片素材并打包即可。 - 3.代码控制
SpriteAtlas sa = Resources.Load<SpriteAtlas>("路径名字");
sa.GetSprite("图片名");
5.UGUI进阶
5.1 事件接口
概述:目前所有控件都只提供了常用的事件监听列表,如果想实现一些类似长按,双击,拖拽等功能是无法制作的。于此我们引入事件接口的概念,让其能处理更多逻辑。
常用事件接口介绍:
代码实例:
public class Test : MonoBehaviour, IPointerEnterHandler
{
public void OnPointerEnter(PointerEventData eventData)
{
print("鼠标进入");
}
}
参数BaseEventData父类详解:
常用参数:
5.2 EventTrigger事件触发器
概念:继承了许多事件接口的组件。
代码添加事件触发器:
(案例:在某组件上添加鼠标抬起事件)
//声明一个希望监听的事件对象
EventTrigger.Entry entry = new EventTrigger.Entry();
//申明 事件的类型
entry.eventID = EventTriggerType.PointerUp;
//监听事件关联
entry.callback.AddListener((data) => {
print("抬起");
});
//加入到EventTrigger
et.triggers.Add(entry);
总结:对对象的管理更加面向对象,减少了自己实现接口的步骤。
实例:配合拖拽事件实现遥感功能
public void OnDrag(PointerEventData eventData)
{
//设置引用对象作为参数nowPos
Vector2 nowPos;
//将屏幕坐标转换为UI本地坐标
//参数一:相对父对象
//参数二:屏幕点
//参数三:摄像机
//参数四:最终得到的点
RectTransformUtility.ScreenPointToLocalPointInRectangle(
this.transform.parent as RectTransform,
eventData.position,
eventData.enterEventCamera,
out nowPos
);
//将当前物体坐标设置为拖拽位置
this.transform.localPosition = nowPos;
}
5.3 Mask遮罩
使用:
- 1.通过在父对象上添加Mask组件即可遮罩子对象
- 2.想要被遮罩的Image需要勾选 Maskable
- 3.只要父对象添加了Mask组件,那么所有UI子对象都会被遮罩
- 4.遮罩父对象的图片制作,不透明的地方显示,透明的地方遮罩
5.4 自动布局组件
水平布局组件:
网格布局组件:
内容大小适配器:
宽高比适配器:
5.5 Canvas Group组
6.UGUI实战
6.1 需求分析
流程图:
类图分析:
遵循一个面板一个类,使用基类书写统一逻辑,以及一个UI管理器,一个登录管理器。
6.2 准备工作
1.新建Unity项目。
2.导入Json管理器工具。
3.创建重要文件夹。
- 1.Resources
- 2.Scripts
- 3.StreamingAssets
- 4.ArtRes
4.导入资源。
5.新建UI场景,引入必要的EventSystem
与Canvas
对象,将Canvas的渲染模式改为摄像机模式,并关联一个新建的UI摄像机,设置其仅渲染UI层,并将Clear Flags改为Depth only,并删除Audio Listener组件,将默认背景改为空,并取消主摄像机的UI渲染。
6.设置画布的自适应(根据美术素材),横屏游戏将适应值拖为1。
6.3 UI基类逻辑
实现功能分析:显示自己,隐藏自己,淡入淡出。
using UnityEngine.Events;
//因为该类不会被初始化,是被子类继承来使用,故可使用抽象类
public abstract class BasePanel : MonoBehaviour
{
//整体控制淡入淡出的画布组件
private CanvasGroup canvasGroup;
//淡入淡出的速度
private float alphaSpeed = 10;
//检测组件是否被显示
private bool isShow;
//淡出面板后执行的逻辑
private UnityAction hideCallBack;
void Awake()
{
//拿到子类对应的画布组件
canvasGroup = GetComponent<CanvasGroup>();
//如果没拿到添加组件
if (canvasGroup == null)
{
canvasGroup = gameObject.AddComponent<CanvasGroup>();
}
}
protected virtual void Start()
{
Init();
}
void Update()
{
//淡入
if (isShow && canvasGroup.alpha < 1)
{
canvasGroup.alpha += alphaSpeed * Time.deltaTime;
if (canvasGroup.alpha >= 1)
canvasGroup.alpha = 1;
}
//淡出
else if (!isShow && canvasGroup.alpha > 0)
{
canvasGroup.alpha -= alphaSpeed * Time.deltaTime;
if (canvasGroup.alpha <= 0)
{
canvasGroup.alpha = 0;
//让管理器 剔除自己
hideCallBack?.Invoke();
}
}
}
//初始化函数声明
protected abstract void Init();
//显示自己
protected virtual void ShowMe()
{
//修改显示参数为显示状态
isShow = true;
//修改Alpha通道(在update中渐变)
canvasGroup.alpha = 0;
}
//隐藏自己
protected virtual void HideMe( UnityAction callback )
{
//修改显示参数为隐藏状态
isShow = false;
//修改Alpha通道(在update中渐变)
canvasGroup.alpha = 1;
//开始淡出时将事件注入容器
hideCallBack = callback;
}
}
6.4 UI管理器的书写
实现目标:单例模式,面板字典,显示面板,隐藏面板,获取面板。
public class UIManager
{
//单例模式
private static UIManager instance;
public static UIManager Instance
{
get { return instance; }
}
//存储当前显示的面板的容器
private Dictionary<string, BasePanel> panelDic = new Dictionary<string, BasePanel>();
//声明父对象
private Transform canvasTrans;
private UIManager()
{
//拿到父对象结点
canvasTrans = GameObject.Find("Canvas").transform;
//过场景时不删除Canvas对象
GameObject.DontDestroyOnLoad(canvasTrans.gameObject);
}
//显示面板
public T ShowPanel<T>() where T : BasePanel
{
//保证泛型T的类型和面板名字一致
string panelName = typeof(T).Name;
//场景中是否已经存在显示的同类面板,如果有,不用单独创建了
if (panelDic.ContainsKey(panelName))
{
return panelDic[panelName] as T;
}
//显示面板就是动态创建面板预制体,设置父对象即可
GameObject panelObj = GameObject.Instantiate(Resources.Load<GameObject>("UI/" + canvasTrans));
panelObj.transform.SetParent(canvasTrans, false);
//得到对应的面板脚本,存储起来即可
T panel = panelObj.GetComponent<T>();
panelDic.Add(panelName, panel);
//调用显示自己逻辑
panel.ShowMe();
return panel;
}
//隐藏面板
//参数isFade:是否希望淡出
public void HidePanel<T>(bool isFade) where T : BasePanel
{
//根据泛型类型得到面板名字
string panelName = typeof(T).Name;
//如果当前显示面板是否存在希望删除面板
if (panelDic.ContainsKey(panelName))
{
if (isFade)
{
panelDic[panelName].HideMe(() =>
{
//面板淡出成功后,删除该面板
GameObject.Destroy(panelDic[panelName].gameObject);
//删除面板后从字典中移除
panelDic.Remove(panelName);
});
}
else
{
//面板淡出成功后,删除该面板
GameObject.Destroy(panelDic[panelName].gameObject);
//删除面板后从字典中移除
panelDic.Remove(panelName);
}
}
}
//获得面板
public T GetPanel<T>() where T : BasePanel
{
string panelName = typeof(T).Name;
if (panelDic.ContainsKey(panelName))
{
return panelDic[panelName] as T;
}
return null;
}
}
6.5 制作提示面板
1.如图拼凑出该模型
2.分析该面板需要实现的功能
- 1.显示隐藏该界面均继承基类即可
- 2.修改提示内容
using UnityEngine.UI;
//提示面板类
public class TipPanel : BasePanel
{
//绑定确认按钮
public Button btn_Sure;
//绑定提示内容
public Text txt_Tip;
//初始化给其面板的确认按钮加上确认逻辑
protected override void Init()
{
btn_Sure.onClick.AddListener(() =>
{
UIManager.Instance.HidePanel<TipPanel>(true);
});
}
//修改提示文字内容
public void ChangeInfo(string info)
{
txt_Tip.text = info;
}
}
6.6 制作登录面板
1.如图拼凑出如图模型
2.分析该面板要实现的功能
- 1.显示隐藏该界面均继承基类即可
- 2.登录数据相关类
//存储登录时玩家提交的数据
public class LoginData
{
//用户名
public string userName;
//密码
public string password;
//是否记住密码
public bool rememberPwd;
//是否自动登录
public bool autoLogin;
}
- 3.登录面板相关逻辑
using UnityEngine.UI;
public class LoginPanel : BasePanel
{
//登录注册按钮组件
public Button btn_Register;
public Button btn_Login;
//输入框组件
public InputField input_UserName;
public InputField input_Password;
//单选框组件
public Toggle toggle_RememberPwd;
public Toggle toggle_AutoLogin;
protected override void Init()
{
//点击注册逻辑
btn_Register.onClick.AddListener(() =>
{
//显示注册面板
//隐藏当前面板
UIManager.Instance.HidePanel<LoginPanel>(true);
});
//点击登录逻辑
btn_Login.onClick.AddListener(() =>
{
//验证用户名和密码是否正确
});
//点击记住密码逻辑
toggle_RememberPwd.onValueChanged.AddListener((isOn) =>
{
//当取消选中记住密码时,如果选择了自动登录,应该自动取消
if (!isOn)
{
toggle_AutoLogin.isOn = false;
}
});
//自动登录逻辑
toggle_AutoLogin.onValueChanged.AddListener((isOn) =>
{
//当选中自动登录时,如果记住密码未被选中,应该让它被选中
if (isOn)
{
toggle_RememberPwd.isOn = true;
}
});
}
public override void ShowMe()
{
base.ShowMe();
//拿到存储的登录数据,并初始化
LoginData loginData = LoginManager.Instance.LoginData;
//初始化单选框
toggle_RememberPwd.isOn = loginData.rememberPwd;
toggle_AutoLogin.isOn = loginData.autoLogin;
//初始化账号密码
input_UserName.text = loginData.userName;
//密码的初始化需要判断是否记住密码
if (toggle_RememberPwd.isOn)
{
input_Password.text = loginData.password;
}
//如果勾选了自动登录,则自动验证账号密码
}
}
6.7 注册面板实现
1.如图拼凑出如图模型
2.分析该面板要实现的功能
- 1.显示隐藏该界面均继承基类即可
- 2.登录数据相关类
6.8 值得注意的一些事
1.背景的比例适配可以将背景单独做成一张面板,然后添加 Aspect Ratio Filter
组件自动适配。
6.9 源码展示
6.9.1 LoginManager登录管理器
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//登录管理器:用于存储与读取用户的登录信息
public class LoginManager
{
//实现单例模式
private static LoginManager instance = new LoginManager();
public static LoginManager Instance
{
get { return instance; }
}
//登录数据
private LoginData loginData;
public LoginData LoginData
{
get { return loginData; }
}
//注册数据
private RegisterData registerData;
public RegisterData RegisterData
{
get { return registerData; }
}
//服务器数据
private List<ServerInfo> serverInfos;
public List<ServerInfo> ServerInfos
{
get { return serverInfos; }
}
//私有构造(防止外部初始化该管理类)
private LoginManager()
{
//如果之前没有登陆数据,则返回默认值
loginData = JsonMgr.Instance.LoadData<LoginData>("LoginData");
//读取注册数据
registerData = JsonMgr.Instance.LoadData<RegisterData>("RegisterData");
//读取服务器数据
serverInfos = JsonMgr.Instance.LoadData<List<ServerInfo>>("ServerInfo");
}
//对外提供保存登陆数据接口
public void SaveLoginData()
{
JsonMgr.Instance.SaveData(loginData, "LoginData");
}
//注册成功后清理数据逻辑
public void ClearLoginData()
{
LoginData.frontServerID = 0;
LoginData.autoLogin = false;
LoginData.rememberPwd = false;
}
//对外提供保存注册数据接口
public void SaveRegisterData()
{
JsonMgr.Instance.SaveData(registerData, "RegisterData");
}
//注册逻辑
public bool Register(string userName,string password)
{
//判断是否存有userName
if (registerData.registerInfo.ContainsKey(userName))
{
//无法注册,用户名已存在
return false;
}
//可以注册,注册逻辑
registerData.registerInfo.Add(userName, password);
//存储数据
SaveRegisterData();
return true;
}
//检测输入的账号密码长度是否合法
public bool CheckLength(string userName,string password)
{
if (userName.Length > 6 && password.Length > 6)
{
return true;
}
return false;
}
//检测输入的账号密码对应
public bool CheckInfo (string userName,string password)
{
//如果检测到用户名存在则继续逻辑
if (registerData.registerInfo.ContainsKey(userName))
{
//再次检测密码是否一致,一致则登录成功
if (registerData.registerInfo[userName] == password)
{
//登录成功
return true;
}
}
return false;
}
}
6.9.2 BasePanel面板基类
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
//因为该类不会被初始化,是被子类继承来使用,故可使用抽象类
public abstract class BasePanel : MonoBehaviour
{
//整体控制淡入淡出的画布组件
private CanvasGroup canvasGroup;
//淡入淡出的速度
private float alphaSpeed = 10;
//检测组件是否被显示
private bool isShow;
//淡出面板后执行的逻辑
private UnityAction hideCallBack;
void Awake()
{
//拿到子类对应的画布组件
canvasGroup = GetComponent<CanvasGroup>();
//如果没拿到添加组件
if (canvasGroup == null)
{
canvasGroup = gameObject.AddComponent<CanvasGroup>();
}
}
protected virtual void Start()
{
Init();
}
void Update()
{
//淡入
if (isShow && canvasGroup.alpha < 1)
{
canvasGroup.alpha += alphaSpeed * Time.deltaTime;
if (canvasGroup.alpha >= 1)
canvasGroup.alpha = 1;
}
//淡出
else if (!isShow && canvasGroup.alpha > 0)
{
canvasGroup.alpha -= alphaSpeed * Time.deltaTime;
if (canvasGroup.alpha <= 0)
{
canvasGroup.alpha = 0;
//让管理器 剔除自己
hideCallBack?.Invoke();
}
}
}
//初始化函数声明
protected abstract void Init();
//显示自己
public virtual void ShowMe()
{
//修改显示参数为显示状态
isShow = true;
//修改Alpha通道(在update中渐变)
canvasGroup.alpha = 0;
}
//隐藏自己
public virtual void HideMe( UnityAction callback )
{
//修改显示参数为隐藏状态
isShow = false;
//修改Alpha通道(在update中渐变)
canvasGroup.alpha = 1;
//开始淡出时将事件注入容器
hideCallBack = callback;
}
}
6.9.3 UIManager UI管理器
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class UIManager
{
//单例模式
private static UIManager instance = new UIManager();
public static UIManager Instance
{
get { return instance; }
}
//存储当前显示的面板的容器
private Dictionary<string, BasePanel> panelDic = new Dictionary<string, BasePanel>();
//声明父对象
private Transform canvasTrans;
private UIManager()
{
//拿到父对象结点
canvasTrans = GameObject.Find("Canvas").transform;
//过场景时不删除Canvas对象
GameObject.DontDestroyOnLoad(canvasTrans.gameObject);
}
//显示面板
public T ShowPanel<T>() where T : BasePanel
{
//保证泛型T的类型和面板名字一致
string panelName = typeof(T).Name;
//场景中是否已经存在显示的同类面板,如果有,不用单独创建了
if (panelDic.ContainsKey(panelName))
{
return panelDic[panelName] as T;
}
//显示面板就是动态创建面板预制体,设置父对象即可
Debug.Log(panelName);
GameObject panelObj = GameObject.Instantiate(Resources.Load<GameObject>("UI/" + panelName));
panelObj.transform.SetParent(canvasTrans, false);
//得到对应的面板脚本,存储起来即可
T panel = panelObj.GetComponent<T>();
panelDic.Add(panelName, panel);
//调用显示自己逻辑
panel.ShowMe();
return panel;
}
//隐藏面板
//参数isFade:是否希望淡出
public void HidePanel<T>(bool isFade) where T : BasePanel
{
//根据泛型类型得到面板名字
string panelName = typeof(T).Name;
//如果当前显示面板是否存在希望删除面板
if (panelDic.ContainsKey(panelName))
{
if (isFade)
{
panelDic[panelName].HideMe(() =>
{
//面板淡出成功后,删除该面板
GameObject.Destroy(panelDic[panelName].gameObject);
//删除面板后从字典中移除
panelDic.Remove(panelName);
});
}
else
{
//删除该面板
GameObject.Destroy(panelDic[panelName].gameObject);
//删除面板后从字典中移除
panelDic.Remove(panelName);
}
}
}
//获得面板
public T GetPanel<T>() where T : BasePanel
{
string panelName = typeof(T).Name;
if (panelDic.ContainsKey(panelName))
{
return panelDic[panelName] as T;
}
return null;
}
}
6.9.4 LoginData登录数据类
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//存储登录时玩家提交的数据
public class LoginData
{
//用户名
public string userName;
//密码
public string password;
//是否记住密码
public bool rememberPwd;
//是否自动登录
public bool autoLogin;
//上次登录的服务器ID
public int frontServerID = 0;
}
6.9.5 RegisterData注册数据类
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//注册数据类,存储玩家注册的数据
public class RegisterData
{
//注册数据(使用字典存储)
public Dictionary<string, string> registerInfo = new Dictionary<string, string>();
}
6.9.6 ServerInfo服务器数据
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//单个服务器数据
public class ServerInfo
{
public int id;
public string name;
public int state;
public int isNew;
}
6.9.7 BGPanel背景面板
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BGPanel : BasePanel
{
protected override void Init()
{
}
}
6.9.8 TipPanel提示面板
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
//提示面板类
public class TipPanel : BasePanel
{
//绑定确认按钮
public Button btn_Sure;
//绑定提示内容
public Text txt_Tip;
//初始化给其面板的确认按钮加上确认逻辑
protected override void Init()
{
btn_Sure.onClick.AddListener(() =>
{
UIManager.Instance.HidePanel<TipPanel>(true);
});
}
//修改提示文字内容
public void ChangeInfo(string info)
{
txt_Tip.text = info;
}
}
6.9.9 LoginPanel登录面板
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class LoginPanel : BasePanel
{
//登录注册按钮组件
public Button btn_Register;
public Button btn_Login;
//输入框组件
public InputField input_UserName;
public InputField input_Password;
//单选框组件
public Toggle toggle_RememberPwd;
public Toggle toggle_AutoLogin;
protected override void Init()
{
//点击注册逻辑
btn_Register.onClick.AddListener(() =>
{
//显示注册面板
UIManager.Instance.ShowPanel<RegisterPanel>();
//隐藏当前面板
UIManager.Instance.HidePanel<LoginPanel>(true);
});
//点击登录逻辑
btn_Login.onClick.AddListener(() =>
{
//验证用户名和密码是否正确
if (LoginManager.Instance.CheckLength(input_UserName.text, input_Password.text))
{
//位数合法
if (LoginManager.Instance.CheckInfo(input_UserName.text, input_Password.text))
{
//登录成功
//记录数据
LoginData login = LoginManager.Instance.LoginData;
login.userName = input_UserName.text;
login.password = input_Password.text;
login.rememberPwd = toggle_RememberPwd.isOn;
login.autoLogin = toggle_AutoLogin.isOn;
//保存登录数据
LoginManager.Instance.SaveLoginData();
//判断上次登录是否选择过服务器
if (login.frontServerID <= 0)
{
//未登录过,打开选择服务器面板
UIManager.Instance.ShowPanel<ChooseServerPanel>();
}
else
{
//登录过,打开服务器面板
UIManager.Instance.ShowPanel<ServerPanel>();
}
//隐藏自己
UIManager.Instance.HidePanel<LoginPanel>(true);
}
else
{
//登录失败
//提供提示信息
UIManager.Instance.ShowPanel<TipPanel>().ChangeInfo("用户名或密码不正确");
}
}
else
{
//登录失败
//提供提示信息
UIManager.Instance.ShowPanel<TipPanel>().ChangeInfo("用户名密码位数必须大于6");
}
});
//点击记住密码逻辑
toggle_RememberPwd.onValueChanged.AddListener((isOn) =>
{
//当取消选中记住密码时,如果选择了自动登录,应该自动取消
if (!isOn)
{
toggle_AutoLogin.isOn = false;
}
});
//自动登录逻辑
toggle_AutoLogin.onValueChanged.AddListener((isOn) =>
{
//当选中自动登录时,如果记住密码未被选中,应该让它被选中
if (isOn)
{
toggle_RememberPwd.isOn = true;
}
});
}
public override void ShowMe()
{
base.ShowMe();
//拿到存储的登录数据,并初始化
LoginData loginData = LoginManager.Instance.LoginData;
//初始化单选框
toggle_RememberPwd.isOn = loginData.rememberPwd;
toggle_AutoLogin.isOn = loginData.autoLogin;
//print(toggle_AutoLogin.isOn);
//print(toggle_RememberPwd.isOn);
//初始化账号密码
input_UserName.text = loginData.userName;
//密码的初始化需要判断是否记住密码
if (toggle_RememberPwd.isOn)
{
input_Password.text = loginData.password;
}
//如果勾选了自动登录,则自动验证账号密码
if (toggle_AutoLogin.isOn)
{
if (LoginManager.Instance.CheckInfo(input_UserName.text, input_Password.text))
{
//根据服务器登录类型决定显示哪个面板
LoginData login = LoginManager.Instance.LoginData;
//判断上次登录是否选择过服务器
if (login.frontServerID <= 0)
{
//未登录过,打开选择服务器面板
UIManager.Instance.ShowPanel<ChooseServerPanel>();
}
else
{
//登录过,打开服务器面板
UIManager.Instance.ShowPanel<ServerPanel>();
}
//隐藏自己
UIManager.Instance.HidePanel<LoginPanel>(false);
}
else
{
UIManager.Instance.ShowPanel<TipPanel>().txt_Tip.text = "用户名或密码错误";
}
}
}
//提供给外部快捷设置用户名和密码的逻辑
public void SetInfo(string userName, string password)
{
input_UserName.text = userName;
input_Password.text = password;
}
}
6.9.10 RegisterPanel注册面板
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class RegisterPanel : BasePanel
{
//输入框组件
public InputField input_UserName;
public InputField input_Password;
//按钮组件
public Button btn_Register;
public Button btn_Cancel;
protected override void Init()
{
//点击取消逻辑
btn_Cancel.onClick.AddListener(() =>
{
//隐藏当前注册面板
UIManager.Instance.HidePanel<RegisterPanel>(true);
//显示登录面板
UIManager.Instance.ShowPanel<LoginPanel>();
});
//点击注册逻辑
btn_Register.onClick.AddListener(() =>
{
//判断长度是否合理
if (LoginManager.Instance.CheckLength(input_UserName.text, input_Password.text))
{
//合理
if (LoginManager.Instance.Register(input_UserName.text, input_Password.text))
{
//注册成功
//清理之前登录数据
LoginManager.Instance.ClearLoginData();
//显示登录面板
LoginPanel loginPanel = UIManager.Instance.ShowPanel<LoginPanel>();
loginPanel.SetInfo(input_UserName.text, input_Password.text);
UIManager.Instance.HidePanel<RegisterPanel>(true);
}
else
{
//未注册成功,提示面板
UIManager.Instance.ShowPanel<TipPanel>().ChangeInfo("用户名已存在");
//将输入框清空
input_UserName.text = "";
input_Password.text = "";
}
}
else
{
//不合理,显示提示面板
UIManager.Instance.ShowPanel<TipPanel>().ChangeInfo("用户名密码长度必须大于6位");
}
});
}
}
6.9.11 ServerPanel服务器面板
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class ServerPanel : BasePanel
{
//按钮组件
public Button btn_Back;
public Button btn_clickServer;
public Button btn_Enter;
//服务器文本
public Text txt_ServerId;
protected override void Init()
{
//给各个组件加功能
btn_Back.onClick.AddListener(() =>
{
//隐藏当前面板
UIManager.Instance.HidePanel<ServerPanel>(true);
//取消自动登录按钮
if (LoginManager.Instance.LoginData.autoLogin)
LoginManager.Instance.LoginData.autoLogin = false;
//显示登录面板
UIManager.Instance.ShowPanel<LoginPanel>();
});
btn_clickServer.onClick.AddListener(() =>
{
//隐藏选服务器面板
UIManager.Instance.HidePanel<ServerPanel>(true);
//弹出服务器面板
UIManager.Instance.ShowPanel<ChooseServerPanel>();
});
btn_Enter.onClick.AddListener(() =>
{
//隐藏当前面板
UIManager.Instance.HidePanel<ServerPanel>(true);
//隐藏背景面板
UIManager.Instance.HidePanel<BGPanel>(true);
//保存登录数据
LoginManager.Instance.SaveLoginData();
//切场景逻辑
});
}
public override void ShowMe()
{
base.ShowMe();
//得到当前服务器信息
int id = LoginManager.Instance.LoginData.frontServerID;
if (id <= 0)
{
txt_ServerId.text = "无";
}
else
{
ServerInfo serverInfo = LoginManager.Instance.ServerInfos[id - 1];
//修改名字
txt_ServerId.text = serverInfo.id + "区 " + serverInfo.name;
}
}
}
6.9.12 ServerLeftItem选服面板左边
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class ServerLeftItem : MonoBehaviour
{
//按钮本身
public Button self;
//显示文本
public Text text;
//开始索引
private int startIndex;
//区间范围
private int endIndex;
//监听各组件的功能
private void Start()
{
self.onClick.AddListener(() =>
{
//点击后改变右边显示的服务器列表
ChooseServerPanel panel = UIManager.Instance.GetPanel<ChooseServerPanel>();
panel.UpdatePanel(startIndex, endIndex);
});
}
//对外提供初始化自身的逻辑
public void InitInfo(int startIndex,int endIndex)
{
this.startIndex = startIndex;
this.endIndex = endIndex;
//修改显示的值
text.text = startIndex + " - " + endIndex + "区";
}
}
6.9.13 ServerRightItem选服面板右边
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.U2D;
using UnityEngine.UI;
public class ServerRightItem : MonoBehaviour
{
//按钮对象
public Button self;
//是否是新服务器
public Image isNew;
//当前状态
public Image state;
//文本内容
public Text text;
//当前按钮代表哪个服务器
private ServerInfo currentServer;
// Start is called before the first frame update
void Start()
{
self.onClick.AddListener(() =>
{
//记录登录信息中的选服信息
LoginManager.Instance.LoginData.frontServerID = currentServer.id;
//隐藏选服面板
UIManager.Instance.HidePanel<ChooseServerPanel>(true);
//显示服务器面板
UIManager.Instance.ShowPanel<ServerPanel>();
});
}
//初始化服务器方法
public void InitServer(ServerInfo serverInfo)
{
currentServer = serverInfo;
//更新按钮上的信息
text.text = serverInfo.id + "区 " + serverInfo.name;
//是否是新服务器
isNew.gameObject.SetActive(serverInfo.isNew == 1 ? true : false);
//更新状态
//加载图集
SpriteAtlas sa = Resources.Load<SpriteAtlas>("login");
switch (serverInfo.state)
{
case 0://火爆
state.sprite = sa.GetSprite("ui_DL_huobao_01");
break;
case 1://繁忙
state.sprite = sa.GetSprite("ui_DL_fanhua_01");
break;
case 2://流畅
state.sprite = sa.GetSprite("ui_DL_liuchang_01");
break;
case 3://维护
state.sprite = sa.GetSprite("ui_DL_weihu_01");
break;
}
}
}