UGUI相关使用

article/2025/10/6 14:35:55

UGUI

文章目录

  • UGUI
    • 1.六大基础组件概述
      • 1.1 Canvas组件
      • 1.2 CanvasScaler组件
      • 1.3 Graphic Raycaster组件
      • 1.4 Event System组件
      • 1.5 Standalone Input Module组件
      • 1.6 RectTransform组件
    • 2.三大基础控件概述
      • 2.1 图像控件Image
      • 2.2 文本控件Text
      • 2.3 RawImage原始图像组件
    • 3.七大组合控件
      • 3.1 Button组件
      • 3.2 Toggle组件
      • 3.3 InputField组件
      • 3.4 Slider滑动条组件
      • 3.5 ScrollBar滚动条组件
      • 3.6 ScrollView滚动视图组件
      • 3.7 DropDown下拉列表组件
    • 4.图集
    • 5.UGUI进阶
      • 5.1 事件接口
      • 5.2 EventTrigger事件触发器
      • 5.3 Mask遮罩
      • 5.4 自动布局组件
      • 5.5 Canvas Group组
    • 6.UGUI实战
      • 6.1 需求分析
      • 6.2 准备工作
      • 6.3 UI基类逻辑
      • 6.4 UI管理器的书写
      • 6.5 制作提示面板
      • 6.6 制作登录面板
      • 6.7 注册面板实现
      • 6.8 值得注意的一些事
      • 6.9 源码展示
        • 6.9.1 LoginManager登录管理器
        • 6.9.2 BasePanel面板基类
        • 6.9.3 UIManager UI管理器
        • 6.9.4 LoginData登录数据类
        • 6.9.5 RegisterData注册数据类
        • 6.9.6 ServerInfo服务器数据
        • 6.9.7 BGPanel背景面板
        • 6.9.8 TipPanel提示面板
        • 6.9.9 LoginPanel登录面板
        • 6.9.10 RegisterPanel注册面板
        • 6.9.11 ServerPanel服务器面板
        • 6.9.12 ServerLeftItem选服面板左边
        • 6.9.13 ServerRightItem选服面板右边

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的基础上(继承)加入了矩形相关,引入了中心点,锚点,长宽等属性。

参数解析

  • 1Pivot:轴心点位置,旋转绕轴心点。
  • 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 RotationTight 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)
{//设置引用对象作为参数nowPosVector2 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场景,引入必要的 EventSystemCanvas对象,将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){//判断是否存有userNameif (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;//上次登录的服务器IDpublic 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 updatevoid 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;}}}

http://chatgpt.dhexx.cn/article/X8F9s35n.shtml

相关文章

Unity UGUI系统

UI系统对比 对 UI 系统的选择取决于是为 Unity 编辑器开发 UI&#xff0c;还是为游戏或应用程序开发运行时 UI。 UI 的类型UI 工具包Unity UI(uGUI)IMGUI注意事项运行时&#xff08;调试&#xff09;✔ *✔✔这指用于调试用途的临时运行时 UI。运行时&#xff08;游戏内&…

UGUI 详解

1.RectTransform RectTransform组件 继承自Transform组件&#xff0c;是2D界面中元素的Transform。 对比Transform增加了新的属性分别是&#xff1a;Anchor&#xff08;锚点&#xff09;和 Pivot&#xff08;轴心点&#xff09;。 属性&#xff1a; localPosition&#xff1a;图…

UGUI学习笔记(八)UGUI不规则响应区域

一、Unity自带的点击策略 在上一篇文章中我们了解到&#xff0c;UI的默认响应区域是UI元素所在的矩形框线内的区域。这也就意味着&#xff0c;当UI的图形为不规则形状时&#xff0c;点击图形的外部也可能会触发事件。 但其实Unity自带了一种不规则区域点击策略。要想使用它&…

[Unity UGUI图集系统]浅谈UGUI图集使用

**写在前面&#xff0c;下面是自己做Demo的时候一些记录吧&#xff0c;参考了很多网上分享的资源 一、打图集 1.准备好素材&#xff08;建议最好是根据图集名称按文件夹分开&#xff09; 2、创建一个SpriteAtlas 3、将素材添加到图集中 4、生成图集 到此&#xff0c;我们的图…

Ngui和Ugui的区别

NGUI的元素更新&#xff1a; UIPanel.LateUpdate采用轮询的方式&#xff0c;每帧都会执行&#xff0c;并且每帧都会有UIPanel.UpdateWidgets这个函数的调用&#xff0c;做的事情就是对这些UI元素的位置、缩放等信息的获取&#xff0c;也就是即使没有变化的UI元素&#xff0c;也…

Unity—UGUI

每日一句&#xff1a;读数、学习 去更远的地方&#xff0c;才能摆脱那些你不屑一顾的圈子 目录 InputFiled输入框 例&#xff1a;用户名和密码 Toggle组件 案例&#xff1a;冷却效果 InputFiled输入框 Text Component 输入文本组件 Text输入内容 Character Limit 输入字符…

【Unity3D】UGUI概述

1 UGUI 与 GUI 区别 GUI控件 在编译时不能可视化&#xff0c;并且界面不太美观&#xff0c;在实际应用中使用的较少。UGUI 在编译时可视化&#xff0c;界面美观&#xff0c;实际应用较广泛。 2 Canvas 渲染模式&#xff08;Render Mode&#xff09; Screen Space - Overlay&a…

怎样使用UGUI

什么是 UGUI UGUI 是 Unity 自带的一套 GUI 系统&#xff0c;含有基本的一些 UI 控件。 UGUI 控件有哪些&#xff1f; 我们常用的有 Canvas&#xff0c;Text&#xff0c;Image&#xff0c;Button&#xff0c;Toggle&#xff0c;Slider&#xff0c;Scroll Bar&#xff0c;Scroll…

Unity3D UGUI系列之合批

目录 1. 什么是UGUI的合批1.1 准备工作1.2 批处理1.3 批处理的意义1.4 UGUI的合批 2 分析工具的使用2.1 Frame Debugger的使用2.2 Profiler-UI的使用 3 UGUI合批规则3.1 UGUI合批初体验3.2 UGUI合批被打断初体验3.3 UGUI合批规则详解3.3.1 合批规则3.3.2 合批规则示例13.3.3 合…

unity中NGUI与UGUI的区别?

什么是UI? UI即User Interface&#xff08;用户界面&#xff09;的简称。泛指用户的操作界面&#xff0c;UI设计主要指界面的样式&#xff0c;美观程度。而使用上&#xff0c;对软件的人机交互、操作逻辑、界面美观的整体设计则是同样重要的另一个门道。好的UI不仅是让软件变得…

【UGUI】UGUI入门,系统介绍

Unity 2017.1.0f3 常用的UI控件 添加UI控件 创建UI控件时&#xff0c;如果没有Canvas和EventSystem系统会自动创建。 Canvas是画布&#xff0c;是所有UI控件的根类&#xff0c;所有UI控件都必须在Canvas上绘制。如果UI控件不在Canvas下&#xff0c;将无法正常渲染显示。 Eve…

UGUI框架

记录最新学习的UGUI框架。 UIType类保存面板基本信息&#xff08;名称、路径&#xff09;&#xff0c;该面板会在具体的面板类里面&#xff08;StartPanel&#xff09;进行实例化。 public class UIType {private string name;public string Name { get > name; }private …

UGUI的简单理解

1.Canvas(画布) UGUI中几乎所有的组件都要在Canvas下搭建 2.EventSysteam(事件系统) 如果进行UI搭建的时候,缺少或删除了EventSysteam的话会导致UGUI中的组件无法交互,无法发生事件. 3.Panel 平时我们进行UI工程搭建的时候,我们都会先创建Panel面板,创建Panel面板的…

UGUI底层

关于UGUI底层的小知识---上 (转雨松momo) 1 | UGUI原理简述 1.1 原理 首先得生成显示UI用的Mesh&#xff0c;如图1-1所示&#xff0c;一个矩形的Mesh&#xff0c;由4个顶点&#xff0c;2个三角形组成&#xff0c;每个顶点都包含UV坐标&#xff0c;如果需要调整颜色&#xf…

UGUI组件详解

什么是 UGUI UGUI 是 Unity 自带的一套 GUI 系统&#xff0c;含有基本的一些 UI 控件。 UGUI 控件有哪些&#xff1f; 我们常用的有 Canvas&#xff0c;Text&#xff0c;Image&#xff0c;Button&#xff0c;Toggle&#xff0c;Slider&#xff0c;Scroll Bar&#xff0c;Scroll…

【Unity基础】ugui的基础知识篇

文章目录 前言一、常用用可视化控件1、Image2、RawImageI.和Image的区别 3、Text组件4、画布是怎么渲染出可视化UI的&#xff1f;II.这里整理一下渲染相关的关系图&#xff0c;如下: 5、关于画布的布局重构 二、Button交互组件1、Button组件的源码以及使用方式2、Button组件是如…

Unity之UGUI详解

UGUI 文章目录 UGUI六大基础组件概述Canvas对象上依附的&#xff1a;CanvasCanvas ScalerGraphic RaycasterRectTransform EventSystem对象上依附的&#xff1a;EventSystemStandalone Input Module Canvas画布组件Screen Space overlayScreen Space CameraWorld Space CanvasS…

using namespace std

整体认识 —— 解决命名冲突 一个简单的C程序&#xff1a; #include<iostream>using namespace std;int main(int argc,char **argv) {cout<<"hello world !"<<endl;system("pause"); // 让程序暂停,按任意键继续 注意&#xff0c;…

K8S:Namespace详解

Namespace概念 Kubernetes 支持多个虚拟集群&#xff0c;它们底层依赖于同一个物理集群&#xff0c;这些虚拟集群被称为命名空间。 命名空间 namespace 是 k8s 集群级别的资源&#xff0c;可以给不同的用户、租户、环境或项目创建对应的命名空间。 在创建pod的时候可以指定p…

TypeScript中的命名空间—namespace

TypeScript中的命名空间—namespace 什么是命名空间&#xff1f;在很多语言中都有这个概念。 命名空间是为了解决命名冲突。比如你在代码的不同地方&#xff0c;都定义了同名但是不同含义的函数、变量等&#xff0c;虽然不提倡这么做&#xff0c;但是有时候需要这么做。那怎么…