5.注册面板
5.1 拼面板
注册面板控件大致和登录面板一致,可以复制过来再改
添加显示隐藏动画,发布面板
5.2 功能制作
创建注册面板脚本,继承Window
public class RegisterWindow : Window
{
}
在登录面板注册按钮点击事件中实际添加显示注册面板逻辑
//注册按钮点击后 做什么
panel.m_btnRe.onClick.Add(() => {
//显示注册面板
UIManager.Instance.ShowWindow<RegisterWindow>();
//隐藏自己
UIManager.Instance.HideWindow<LoginWindow>();
});
注册面板添加显示隐藏动效逻辑
protected override void DoShowAnimation()
{
this.contentPane.GetTransition("show").Play(base.DoShowAnimation);
}
protected override void DoHideAnimation()
{
this.contentPane.GetTransition("hide").Play(base.DoHideAnimation);
}
声明注册数据类,用字典来存储和管理
[System.Serializable]
public class RegisterData
{
//用于存储所有的注册相关数据
public Dictionary<string, string> registerDic = new Dictionary<string, string>();
}
在登录管理器引用一个登录数据对象,在构造函数中从二进制数据管理器中得到,没有就new一个。添加存储登录数据方法,用二进制数据管理器存储。添加注册用户方法,传入用户名和密码,判断是否有同名账号,如果没有重名那么直接注册添加到注册数据字典后存储登录数据。添加验证登录是否成功的方法,判断注册数据字典用户名和密码是否相同。
/// <summary>
/// 用于管理登录相关数据的管理器
/// </summary>
public class LoginMgr
{
private static LoginMgr instance = new LoginMgr();
public static LoginMgr Instance => instance;
//注册数据对象
private RegisterData registerData;
private LoginMgr()
{
//从本地得到注册数据 如果没有得到 那么证明没有 直接new一个 数据即可
registerData = BinaryDataMgr.Instance.Load<RegisterData>("RegisterData");
if (registerData == null)
registerData = new RegisterData();
}
/// <summary>
/// 存储注册相关数据2进制到本地
/// </summary>
public void SaveRegisterData()
{
BinaryDataMgr.Instance.Save(registerData, "RegisterData");
}
/// <summary>
/// 注册用户方法
/// </summary>
/// <param name="userName">用户名</param>
/// <param name="passWord">密码</param>
/// <returns>true注册成功 false 注册失败</returns>
public bool RegisterUser(string userName, string passWord)
{
//判断是否有同名账号
if(registerData.registerDic.ContainsKey(userName))
{
return false;
}
//如果没有重名 那么直接注册
registerData.registerDic.Add(userName, passWord);
//本地存储
SaveRegisterData();
//注册成功
return true;
}
/// <summary>
/// 验证登录是否成功的方法
/// </summary>
/// <param name="userName"></param>
/// <param name="passWord"></param>
/// <returns></returns>
public bool CheckInfo(string userName, string passWord)
{
//首先判断有没有这个用户
if(registerData.registerDic.ContainsKey(userName))
{
//密码是否相同
if(registerData.registerDic[userName] == passWord)
{
return true;
}
}
//用户名和密码至少有一个不合法
return false;
}
}
登录面板添加提供给外部设置账号和密码输入框内容的方法
/// <summary>
/// 提供给外部设置账号和密码输入框内容的方法
/// </summary>
/// <param name="userName"></param>
/// <param name="passWord"></param>
public void SetInfo(string userName, string passWord)
{
UI_LoginWindow panel = this.contentPane as UI_LoginWindow;
panel.m_inputAN.text = userName;
panel.m_inputPW.text = passWord;
}
在注册面板脚本中重写初始化方法。设置contentPane为创建出来的注册面板,全屏显示。添加点击注册面板确定按钮事件,首先判断账号密码的合法性,不合法弹出提示面板。合法如果注册成功就回到登录面板,把账号和密码给别人填上隐藏自己。合法如果注册失败,清空账号密码输入框填写的不合法内容。关闭按钮添加显示登录面板隐藏注册面板的事件。
protected override void OnInit()
{
base.OnInit();
this.contentPane = UIManager.Instance.LoadComponent("Login", "RegisterWindow");
this.MakeFullScreen();
UI_RegisterWindow panel = this.contentPane as UI_RegisterWindow;
//点击确定按钮做什么
panel.m_btnSure.onClick.Add(()=> {
//合法性判断
if( panel.m_inputAN.text.Length <= 6 ||
panel.m_inputPW.text.Length <= 3)
{
//显示提示面板 提醒它 账号密码的规范
UIManager.Instance.ShowWindow<TipWindow>().ChangeInfo("账号必须大于6位,密码必须大于3位");
//清空账号密码输入框填写的不合法内容
panel.m_inputAN.text = "";
panel.m_inputPW.text = "";
return;
}
//合法 那么进行注册
if( LoginMgr.Instance.RegisterUser(panel.m_inputAN.text, panel.m_inputPW.text) )
{
//注册成功
//就应该回到 登录界面 然后把账号和密码给别人填上
LoginWindow loginPanel = UIManager.Instance.ShowWindow<LoginWindow>();
loginPanel.SetInfo(panel.m_inputAN.text, panel.m_inputPW.text);
//隐藏自己
UIManager.Instance.HideWindow<RegisterWindow>();
}
else
{
//注册失败
UIManager.Instance.ShowWindow<TipWindow>().ChangeInfo("用户名存在");
//清空账号密码输入框填写的不合法内容
panel.m_inputAN.text = "";
panel.m_inputPW.text = "";
}
});
panel.m_btnClose.onClick.Add(() =>
{
//显示登录面板
UIManager.Instance.ShowWindow<LoginWindow>();
//隐藏自己
UIManager.Instance.HideWindow<RegisterWindow>();
});
}
让登录面板的显示动画基类方法先执行。因为显示动画基类方法会执行OnShown,OnShown中我们写了初始化相关的逻辑。延迟执行OnShown会导致我们在注册面板的使用的SetInfo更早执行,设置好的账号密码会被覆盖。
protected override void DoShowAnimation()
{
base.DoShowAnimation();
this.contentPane.GetTransition("show").Play();
}
在登录面板补充点击确定按钮逻辑。点击判断输入内容合法后验证用户名和密码。如果登录成功记录数据到登录数据中并保存。根据上一次服务器ID判断需要跳到哪个面板并隐藏登录面板。验证用户名密码失败则显示提示面板。
//确定按钮点击后 做什么
panel.m_btnSure.onClick.Add(() => {
//判断 输入内容的合法性
if (panel.m_inputAN.text.Length <= 6 ||
panel.m_inputPW.text.Length <= 3)
{
UIManager.Instance.ShowWindow<TipWindow>().ChangeInfo("账号必须大于6位,密码必须大于3位");
return;
}
//验证用户名和密码 是否输入正确
//之后完成了注册功能 再回过头来写
if (LoginMgr.Instance.CheckInfo(panel.m_inputAN.text, panel.m_inputPW.text))
{
//登录成功
//记录登录相关数据
//记录账号和密码数据
LoginMgr.Instance.loginData.userName = panel.m_inputAN.text;
LoginMgr.Instance.loginData.passWord = panel.m_inputPW.text;
//记录两个复选按钮选中情况
LoginMgr.Instance.loginData.rememberPw = panel.m_cbPW.selected;
LoginMgr.Instance.loginData.autoLogin = panel.m_cbAuto.selected;
//保存到本地 下一次运行游戏时
LoginMgr.Instance.SaveLoginData();
//决定打开哪个面板
//第一次登录 需要打开 选服面板
if (LoginMgr.Instance.loginData.frontServerID == 0)
{
//打开选服面板
}
else
{
//打开服务器面板
}
//隐藏自己
UIManager.Instance.HideWindow<LoginWindow>();
}
else
{
//登录失败
UIManager.Instance.ShowWindow<TipWindow>().ChangeInfo("账号或密码错误");
}
});
在注册面板的OnShown方法中补充自动登录逻辑。逻辑和点击按钮事件大同小异。
/// <summary>
/// 显示时会自动调用的方法
/// </summary>
protected override void OnShown()
{
base.OnShown();
//初始化面板基础内容
//得到登录相关数据
LoginData data = LoginMgr.Instance.loginData;
//得到组件拓展类对象
UI_LoginWindow panel = this.contentPane as UI_LoginWindow;
//两个复选按钮 是否选中
panel.m_cbPW.selected = data.rememberPw;
panel.m_cbAuto.selected = data.autoLogin;
//账号密码 显示的内容
panel.m_inputAN.text = data.userName;
panel.m_inputPW.text = data.passWord;
//如果需要自动登录
if(data.autoLogin)
{
//之后完成了注册功能 再回过头来写 自动登录
//验证用户名和密码 是否输入正确
//之后完成了注册功能 再回过头来写
if (LoginMgr.Instance.CheckInfo(panel.m_inputAN.text, panel.m_inputPW.text))
{
//决定打开哪个面板
//第一次登录 需要打开 选服面板
if (LoginMgr.Instance.loginData.frontServerID == 0)
{
//打开选服面板
}
else
{
//打开服务器面板
}
//隐藏自己
UIManager.Instance.HideWindow<LoginWindow>();
}
else
{
//登录失败
UIManager.Instance.ShowWindow<TipWindow>().ChangeInfo("账号或密码错位");
}
}
}
在OnShown执行UIManager.Instance.HideWindow();会出现问题。是因为我们在UIManager中win.Show()后,会先走进win的OnShown函数,再把面板添加到字典上。这时如果是自动登录,HideWindow时windowDic还没有LoginWindow,所以自动登录不起作用。调整成先添加到字典再Show即可。
//创建并显示面板
T win = new T();
//改成先记录在字典中
windowDic.Add(windowName, win);
//再进行显示 当存储了再去显示 避免显示时调用隐藏不执行
win.Show();
5.3 代码
RegisterData
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[System.Serializable]
public class RegisterData
{
//用于存储所有的注册相关数据
public Dictionary<string, string> registerDic = new Dictionary<string, string>();
}
LoginMgr
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 用于管理登录相关数据的管理器
/// </summary>
public class LoginMgr
{
private static LoginMgr instance = new LoginMgr();
public static LoginMgr Instance => instance;
//登录数据对象
public LoginData loginData;
//注册数据对象
private RegisterData registerData;
private LoginMgr()
{
loginData = BinaryDataMgr.Instance.Load<LoginData>("LoginData");
if (loginData == null)
loginData = new LoginData();
//从本地得到注册数据 如果没有得到 那么证明没有 直接new一个 数据即可
registerData = BinaryDataMgr.Instance.Load<RegisterData>("RegisterData");
if (registerData == null)
registerData = new RegisterData();
}
/// <summary>
/// 存储登录数据2进制文件到本地
/// </summary>
public void SaveLoginData()
{
BinaryDataMgr.Instance.Save(loginData, "LoginData");
}
/// <summary>
/// 存储注册相关数据2进制到本地
/// </summary>
public void SaveRegisterData()
{
BinaryDataMgr.Instance.Save(registerData, "RegisterData");
}
/// <summary>
/// 注册用户方法
/// </summary>
/// <param name="userName">用户名</param>
/// <param name="passWord">密码</param>
/// <returns>true注册成功 false 注册失败</returns>
public bool RegisterUser(string userName, string passWord)
{
//判断是否有同名账号
if(registerData.registerDic.ContainsKey(userName))
{
return false;
}
//如果没有重名 那么直接注册
registerData.registerDic.Add(userName, passWord);
//本地存储
SaveRegisterData();
//注册成功
return true;
}
/// <summary>
/// 验证登录是否成功的方法
/// </summary>
/// <param name="userName"></param>
/// <param name="passWord"></param>
/// <returns></returns>
public bool CheckInfo(string userName, string passWord)
{
//首先判断有没有这个用户
if(registerData.registerDic.ContainsKey(userName))
{
//密码是否相同
if(registerData.registerDic[userName] == passWord)
{
return true;
}
}
//用户名和密码至少有一个不合法
return false;
}
}
UIManager
using FairyGUI;
using Login;
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class UIManager
{
private static UIManager instance = new UIManager();
public static UIManager Instance => instance;
//用于存储已经显示的 UI面板
private Dictionary<string, GComponent> panelDic = new Dictionary<string, GComponent>();
//用于存储已经显示的 窗口
private Dictionary<string, Window> windowDic = new Dictionary<string, Window>();
private UIManager()
{
//默认字体
UIConfig.defaultFont = "UI/STHUPO";
//默认音效
UIPackage.AddPackage("UI/Public");
UIConfig.buttonSound = (NAudioClip)UIPackage.GetItemAssetByURL("ui://Public/btnMusic");
//适配相关的设置
GRoot.inst.SetContentScaleFactor(1365, 768, UIContentScaler.ScreenMatchMode.MatchHeight);
//设置模态半透明程度
UIConfig.modalLayerColor = new Color(0, 0, 0, 0.5f);
//注册相关的代码
LoginBinder.BindAll();
}
//组件名和面板类名 是一致的
public T ShowPanel<T>(string packageName) where T:GComponent
{
Type panelType = typeof(T);
string panelName = panelType.Name;
//如果字典中有该面板的名字 证明已经创建过了 直接返回即可
if (panelDic.ContainsKey(panelName))
{
panelDic[panelName].visible = true;
return panelDic[panelName] as T;
}
//加载包和依赖包
//由于从Resources文件夹中加载包 会帮助我们判断重复没有 所以 这里既是重复执行也没什么问题
UIPackage package = UIPackage.AddPackage("UI/" + packageName);
foreach (var item in package.dependencies)
{
UIPackage.AddPackage("UI/" + item["name"]);
}
//创建组件面板
GComponent panel = UIPackage.CreateObject(packageName, panelName).asCom;
//把组件的尺寸设置的和逻辑分辨率一致
panel.MakeFullScreen();
GRoot.inst.AddChild(panel);
//和父对象建立 宽高关联 这样 分辨率变化时 面板也不会出问题
panel.AddRelation(GRoot.inst, RelationType.Size);
//进行批处理 DC优化 开关开启
panel.fairyBatching = true;
//把当前显示的面板存起来 用于之后的隐藏
panelDic.Add(panelName, panel);
//把父类转换成对应的 子类
return panel as T;
}
//显示窗口方法
public T ShowWindow<T>() where T:Window,new()
{
Type type = typeof(T);
string windowName = type.Name;
//判断有没有面板
if (windowDic.ContainsKey(windowName))
{
windowDic[windowName].Show();
return windowDic[windowName] as T;
}
//创建并显示面板
T win = new T();
//记录字典中
windowDic.Add(windowName, win);
//当存储了再去显示 避免显示时调用隐藏不执行
win.Show();
return win;
}
public void HidePanel<T>(bool isDispose = false) where T:GComponent
{
Type panelType = typeof(T);
string panelName = panelType.Name;
//如果没有面板显示着 就直接返回
if (!panelDic.ContainsKey(panelName))
return;
//希望移除面板
if( isDispose )
{
//移除面板 并且从字典中移除
panelDic[panelName].Dispose();
panelDic.Remove(panelName);
}
//希望只是失活
else
{
panelDic[panelName].visible = false;
}
}
//隐藏窗口方法
public void HideWindow<T>(bool isDispose = false)
{
Type type = typeof(T);
string windowName = type.Name;
if (windowDic.ContainsKey(windowName))
{
if(isDispose)
{
windowDic[windowName].Dispose();
windowDic.Remove(windowName);
}
else
{
windowDic[windowName].Hide();
}
}
}
public T GetPanel<T>() where T:GComponent
{
Type panelType = typeof(T);
string panelName = panelType.Name;
//如果有这个面板 直接返回
if (panelDic.ContainsKey(panelName))
return panelDic[panelName] as T;
return null;
}
//得到窗口
public T GetWindow<T>() where T:Window
{
Type type = typeof(T);
string windowName = type.Name;
if (windowDic.ContainsKey(windowName))
{
return windowDic[windowName] as T;
}
return null;
}
//主要用于销毁所有面板 和 资源垃圾回收的方法
public void ClearPanel(bool isGC = false)
{
//销毁所有面板 并且清空字典
foreach (var item in panelDic.Values)
{
item.Dispose();
}
panelDic.Clear();
if(isGC)
{
//释放所有包资源
UIPackage.RemoveAllPackages();
//垃圾回收
GC.Collect();
}
}
//清除所有窗口
public void ClearWindow(bool isGC = false)
{
//销毁所有面板 并且清空字典
foreach (var item in windowDic.Values)
{
item.Dispose();
}
windowDic.Clear();
if(isGC)
{
//释放所有包资源
UIPackage.RemoveAllPackages();
//垃圾回收
GC.Collect();
}
}
/// <summary>
/// 加载组件
/// </summary>
/// <param name="packageName">包名</param>
/// <param name="componentName">组件名</param>
/// <returns></returns>
public GComponent LoadComponent(string packageName, string componentName)
{
//加载包
UIPackage package = UIPackage.AddPackage("UI/" + packageName);
//加载依赖包
foreach (var item in package.dependencies)
{
UIPackage.AddPackage("UI/" + item["name"]);
}
GComponent component = UIPackage.CreateObject(packageName, componentName).asCom;
//component.MakeFullScreen();
//优化dc,只需要把面板组件fairyBatching设置为true
component.fairyBatching = true;
return component;
}
}
RegisterWindow
using FairyGUI;
using Login;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class RegisterWindow : Window
{
protected override void OnInit()
{
base.OnInit();
this.contentPane = UIManager.Instance.LoadComponent("Login", "RegisterWindow");
this.MakeFullScreen();
UI_RegisterWindow panel = this.contentPane as UI_RegisterWindow;
//点击确定按钮做什么
panel.m_btnSure.onClick.Add(()=> {
//合法性判断
if( panel.m_inputAN.text.Length <= 6 ||
panel.m_inputPW.text.Length <= 3)
{
//显示提示面板 提醒它 账号密码的规范
UIManager.Instance.ShowWindow<TipWindow>().ChangeInfo("账号必须大于6位,密码必须大于3位");
//清空账号密码输入框填写的不合法内容
panel.m_inputAN.text = "";
panel.m_inputPW.text = "";
return;
}
//合法 那么进行注册
if( LoginMgr.Instance.RegisterUser(panel.m_inputAN.text, panel.m_inputPW.text) )
{
//注册成功
//就应该回到 登录界面 然后把账号和密码给别人填上
LoginWindow loginPanel = UIManager.Instance.ShowWindow<LoginWindow>();
loginPanel.SetInfo(panel.m_inputAN.text, panel.m_inputPW.text);
//隐藏自己
UIManager.Instance.HideWindow<RegisterWindow>();
}
else
{
//注册失败
UIManager.Instance.ShowWindow<TipWindow>().ChangeInfo("用户名存在");
//清空账号密码输入框填写的不合法内容
panel.m_inputAN.text = "";
panel.m_inputPW.text = "";
}
});
panel.m_btnClose.onClick.Add(() =>
{
//显示登录面板
UIManager.Instance.ShowWindow<LoginWindow>();
//隐藏自己
UIManager.Instance.HideWindow<RegisterWindow>();
});
}
protected override void DoShowAnimation()
{
this.contentPane.GetTransition("show").Play(base.DoShowAnimation);
}
protected override void DoHideAnimation()
{
this.contentPane.GetTransition("hide").Play(base.DoHideAnimation);
}
}
LoginWindow
using FairyGUI;
using Login;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class LoginWindow : Window
{
protected override void OnInit()
{
base.OnInit();
this.contentPane = UIManager.Instance.LoadComponent("Login", "LoginWindow");
this.contentPane.MakeFullScreen();
//得到组件拓展类对象
UI_LoginWindow panel = this.contentPane as UI_LoginWindow;
//确定按钮点击后 做什么
panel.m_btnSure.onClick.Add(() => {
//判断 输入内容的合法性
if (panel.m_inputAN.text.Length <= 6 ||
panel.m_inputPW.text.Length <= 3)
{
UIManager.Instance.ShowWindow<TipWindow>().ChangeInfo("账号必须大于6位,密码必须大于3位");
return;
}
//验证用户名和密码 是否输入正确
//之后完成了注册功能 再回过头来写
if (LoginMgr.Instance.CheckInfo(panel.m_inputAN.text, panel.m_inputPW.text))
{
//登录成功
//记录登录相关数据
//记录账号和密码数据
LoginMgr.Instance.loginData.userName = panel.m_inputAN.text;
LoginMgr.Instance.loginData.passWord = panel.m_inputPW.text;
//记录两个复选按钮选中情况
LoginMgr.Instance.loginData.rememberPw = panel.m_cbPW.selected;
LoginMgr.Instance.loginData.autoLogin = panel.m_cbAuto.selected;
//保存到本地 下一次运行游戏时
LoginMgr.Instance.SaveLoginData();
//决定打开哪个面板
//第一次登录 需要打开 选服面板
if (LoginMgr.Instance.loginData.frontServerID == 0)
{
//打开选服面板
}
else
{
//打开服务器面板
}
//隐藏自己
UIManager.Instance.HideWindow<LoginWindow>();
}
else
{
//登录失败
UIManager.Instance.ShowWindow<TipWindow>().ChangeInfo("账号或密码错误");
}
});
//注册按钮点击后 做什么
panel.m_btnRe.onClick.Add(() => {
//显示注册面板
UIManager.Instance.ShowWindow<RegisterWindow>();
//隐藏自己
UIManager.Instance.HideWindow<LoginWindow>();
});
//当记住密码状态改变时 做什么
panel.m_cbPW.onChanged.Add(() => {
//记住密码取消勾选时 强行取消勾选自动登录
if (!panel.m_cbPW.selected)
panel.m_cbAuto.selected = false;
});
//当自动登录时 做什么
panel.m_cbAuto.onChanged.Add(() =>
{
//自动登录勾选上 强行勾选上 记住密码
if (panel.m_cbAuto.selected)
panel.m_cbPW.selected = true;
});
}
/// <summary>
/// 显示时会自动调用的方法
/// </summary>
protected override void OnShown()
{
base.OnShown();
//初始化面板基础内容
//得到登录相关数据
LoginData data = LoginMgr.Instance.loginData;
//得到组件拓展类对象
UI_LoginWindow panel = this.contentPane as UI_LoginWindow;
//两个复选按钮 是否选中
panel.m_cbPW.selected = data.rememberPw;
panel.m_cbAuto.selected = data.autoLogin;
//账号密码 显示的内容
panel.m_inputAN.text = data.userName;
panel.m_inputPW.text = data.passWord;
//如果需要自动登录
if(data.autoLogin)
{
//之后完成了注册功能 再回过头来写 自动登录
//验证用户名和密码 是否输入正确
//之后完成了注册功能 再回过头来写
if (LoginMgr.Instance.CheckInfo(panel.m_inputAN.text, panel.m_inputPW.text))
{
//决定打开哪个面板
//第一次登录 需要打开 选服面板
if (LoginMgr.Instance.loginData.frontServerID == 0)
{
//打开选服面板
}
else
{
//打开服务器面板
}
//隐藏自己
UIManager.Instance.HideWindow<LoginWindow>();
}
else
{
//登录失败
UIManager.Instance.ShowWindow<TipWindow>().ChangeInfo("账号或密码错位");
}
}
}
/// <summary>
/// 提供给外部设置账号和密码输入框内容的方法
/// </summary>
/// <param name="userName"></param>
/// <param name="passWord"></param>
public void SetInfo(string userName, string passWord)
{
UI_LoginWindow panel = this.contentPane as UI_LoginWindow;
panel.m_inputAN.text = userName;
panel.m_inputPW.text = passWord;
}
protected override void DoShowAnimation()
{
base.DoShowAnimation();
this.contentPane.GetTransition("show").Play();
}
protected override void DoHideAnimation()
{
this.contentPane.GetTransition("hide").Play(base.DoHideAnimation);
}
}
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com