unity教程:登陆与注册系统,数据库功能
using UnityEngine;
using TMPro;
/// <summary>
/// 登录注册系统管理类
/// </summary>
public class LoginManager : MonoBehaviour
{
//---游戏界面---//
private GameObject loginBefore;
private GameObject loginAfter;
//---登录账号与注册账号界面---//
private GameObject login;
private GameObject erllon;
//---登录账号输入密码以及输入密码框---//
private TMP_InputField loginName;
private TMP_InputField loginPwd;
//---注册账号输入密码以及输入密码框---//
private TMP_InputField erllonName;
private TMP_InputField erllonPwd;
//---对话框---//
private PromptBox promptBox;
//---数据库实例---//
public DataBase dataBase;
/// <summary>
/// 获得场景中的组件给变量赋值
/// </summary>
private void Awake()
{
Singleton = this;
loginBefore = transform.parent.transform.GetChild(2).gameObject;
loginAfter = transform.parent.transform.GetChild(3).gameObject;
login = transform.parent.transform.GetChild(4).GetChild(0).gameObject;
erllon = transform.parent.transform.GetChild(4).GetChild(1).gameObject;
promptBox = transform.parent.transform.GetChild(4).GetChild(2).gameObject.GetComponent<PromptBox>();
loginName = transform.parent.transform.GetChild(4).GetChild(0).GetChild(1).GetComponent<TMP_InputField>();
loginPwd = transform.parent.transform.GetChild(4).GetChild(0).GetChild(2).GetComponent<TMP_InputField>();
erllonName = transform.parent.transform.GetChild(4).GetChild(1).GetChild(1).GetComponent<TMP_InputField>();
erllonPwd = transform.parent.transform.GetChild(4).GetChild(1).GetChild(2).GetComponent<TMP_InputField>();
}
/// <summary>
/// 加载初始化
/// </summary>
private void Start()
{
//实例化数据库
dataBase = new DataBase();
//初始化游戏
Init();
}
/// <summary>
/// 管理类加载数据初始化
/// </summary>
/// <returns>返回加载成功结果的数据</returns>
private void Init()
{
//读取本地账号信息(如果是首次读取则初始化为null)
string name = PlayerPrefs.GetString("csName", "null");
string password = PlayerPrefs.GetString("csPwd", "null");
//判断保存在本地的账号密码是否正确
if (dataBase.IsPassword(name,password)==false || name == "null")
{
loginBefore.SetActive(true);
loginAfter.SetActive(false);
}
else
{
loginBefore.SetActive(false);
loginAfter.SetActive(true);
}
//将登录账号与注册账号界面关闭
login.SetActive(false);
erllon.SetActive(false);
}
//--------------------封装方法--------------------//
/// <summary>
/// 登录账号方法
/// </summary>
/// <param name="name">输入的账号名字</param>
/// <param name="password">输入的账号密码</param>
/// <param name="promptBox">提示框</param>
private void LoginAccount(TMP_InputField name, TMP_InputField password, PromptBox promptBox)
{
//使用元组 快速赋值 通过元组析构 拆分成多个变量
var (_name, _password, _promptBox) = (name.text, password.text,promptBox);
//检测输入框是否为空
if (_name == string.Empty || _password == string.Empty)
{
//输入框为空提示
_promptBox.ShowBox("输入框不可为空");
return;
}
//检测是否存在该账号
if (dataBase.IsName(_name))
{
//检测密码是否正确
if(dataBase.IsPassword(_name,_password))
{
//---密码正确执行剩下操作---//
//将已经登录的账号密码保存到本地
PlayerPrefs.SetString("csName", _name);
PlayerPrefs.SetString("csPwd", _password);
PlayerPrefs.SetInt("csValue", dataBase.GetAccountValue(_name));
//---更新游戏界面---//
loginBefore.SetActive(false);
loginAfter.SetActive(true);
login.SetActive(false);
erllon.SetActive(false);
//登录成功提示
_promptBox.ShowBox("登录成功");
return;
}
//密码错误提示
_promptBox.ShowBox("账号不存在或者密码错误");
return;
}
//当账号不存在时
else
{
//账号不存在提示
_promptBox.ShowBox("账号不存在或者密码错误");
return;
}
}
/// <summary>
/// 注册账号方法
/// </summary>
/// <param name="name">输入的账号名字</param>
/// <param name="password">输入的账号密码</param>
/// <param name="promptBox">提示框</param>
private void ErllonAccount(TMP_InputField name, TMP_InputField password, PromptBox promptBox)
{
var (_name, _password, _promptBox) = (name.text, password.text, promptBox);
//检测输入框是否为空
if (_name == string.Empty || _password == string.Empty)
{
//输入框为空提示
_promptBox.ShowBox("输入框不可为空");
return;
}
//检测是否不存在该账号
if (!dataBase.IsName(_name))
{
//创建临时账号信息
Account account = new Account()
{
Name = _name,
Password = _password,
Value = 0
};
//添加账号至游戏数据中
dataBase.Add(account);
//---更新游戏界面---//
login.SetActive(false);
erllon.SetActive(false);
//注册成功提示
_promptBox.ShowBox("注册成功");
return;
}
//当账号存在时
else
{
//账号存在提示
_promptBox.ShowBox("当前账号已存在");
return;
}
}
/// <summary>
/// 对话框显示
/// </summary>
/// <param name="promptBox">需要显示的对话框</param>
/// <param name="body">对话框显示的内容</param>
private void ShowBox(PromptBox promptBox, string body)
{
promptBox.ShowBox(body);
}
//--------------------按钮事件部分--------------------//
/// <summary>
/// 登录账号方法
/// </summary>
public void LoginAccount()
{
LoginAccount(loginName, loginPwd, promptBox);
}
/// <summary>
/// 注册账号方法
/// </summary>
public void ErllonAccount()
{
ErllonAccount(erllonName, erllonPwd, promptBox);
}
/// <summary>
/// 退出游戏方法
/// </summary>
public void QuitGame()
{
Application.Quit();
}
/// <summary>
/// 退出登录方法
/// </summary>
public void QuitLogin()
{
//---将本地数据删除---//
PlayerPrefs.SetString("csName", "null");
PlayerPrefs.SetString("csPwd", "null");
PlayerPrefs.SetInt("csValue", 0);
//---更新游戏界面---//
loginBefore.SetActive(true);
loginAfter.SetActive(false);
login.SetActive(false);
erllon.SetActive(false);
}
/// <summary>
/// 对话框显示
/// </summary>
/// <param name="body">对话框显示的内容</param>
public void ShowBox(string body)
{
ShowBox(promptBox, body);
}
//--------------------管理类单例模式--------------------//
private static LoginManager Singleton;
public static LoginManager Instance
{
get
{
if (Singleton != null)
return Singleton;
Singleton = FindObjectOfType<LoginManager>();
if (Singleton == null)
{
Singleton = new GameObject("loginManager").AddComponent<LoginManager>();
}
else
{
foreach (var item in FindObjectsOfType<SlackerSingleton>())
{
if (item != Singleton)
Destroy(item.gameObject);
}
}
return Singleton;
}
}
}
using System.Collections.Generic;
/// <summary>
/// 数据库类 (用于保存与读取本地数据)
/// </summary>
public class DataBase
{
/// <summary>
/// 数据库数据
/// </summary>
private AccountData data = new AccountData();
public DataBase()
{
data = LoginEventHandler.CallLoadData();
}
~DataBase()
{
LoginEventHandler.CallSavaData(data);
}
//--------------------增删改查部分(公开部分)--------------------//
/// <summary>
/// 添加账号
/// </summary>
/// <param name="account">需要添加的账号信息</param>
public bool Add(Account account)
{
if (!IsName(account.Name))
{
Add(account.Name,account.Password,account.Value);
return true;
}
return false;
}
/// <summary>
/// 删除账号
/// </summary>
/// <param name="name">需要删除的账号信息</param>
public bool Remove(Account account)
{
if (IsPassword(account.Name, account.Password))
{
Remove(account.Name);
return true;
}
return false;
}
/// <summary>
/// 修改账号
/// </summary>
/// <param name="account">需要修改的账号</param>
/// <param name="account1">需要修改成的账号信息</param>
public bool ReviseAccount(Account account, Account account1)
{
if (IsPassword(account.Name, account.Password))
{
ReviseAccount(account.Name, account1);
return true;
}
return false;
}
/// <summary>
/// 获得所有账号的名字
/// </summary>
/// <returns>返回所有账号名字数组</returns>
public List<string> GetAllAccountName()
{
List<string> vs = new List<string>();
for (int i = 0; i < data.data.Count; i++)
{
vs.Add(data.data[i].Name);
}
return vs;
}
//--------------------增删改查部分(安全部分)--------------------//
/// <summary>
/// 添加账号
/// </summary>
/// <param name="name">账号名字</param>
/// <param name="password">账号密码</param>
/// <returns>返回添加结果</returns>
private bool Add(string name, string password)
{
if (IsName(name))
{
Add(name, password, 0);
return true;
}
return false;
}
/// <summary>
/// 删除账号
/// </summary>
/// <param name="name">需要删除的账号名字</param>
/// <param name="password">需要删除的账号密码</param>
public bool Remove(string name, string password)
{
if (IsPassword(name, password))
{
Remove(name);
return true;
}
return false;
}
/// <summary>
/// 查找账号
/// </summary>
/// <param name="name">需要查找的账号名字</param>
/// <param name="password">需要查找的账号名字</param>
/// <returns>返回查找结果</returns>
public Account GetAccount(string name, string password)
{
if (IsPassword(name, password))
{
return GetAccount(name);
}
return null;
}
/// <summary>
/// 查看该账号的资源
/// </summary>
/// <param name="name">需要查看的账号名字</param>
/// <param name="password">需要查看的密码</param>
/// <returns>返回账号值</returns>
public int GetAccountValue(string name)
{
if (IsName(name))
{
return GetAccount(name).Value;
}
return 0;
}
//--------------------增删改查部分(私密部分)--------------------//
/// <summary>
/// 添加账号
/// </summary>
/// <param name="name">账号名字</param>
/// <param name="password">账号的密码</param>
/// <param name="value">账号资源</param>
private void Add(string name, string password,int value)
{
data.data.Add(new Account()
{
Name = name,
Password = password,
Value = value
});
LoginEventHandler.CallSavaData(data);
}
/// <summary>
/// 删除账号
/// </summary>
/// <param name="name">需要删除的账号名字</param>
private void Remove(string name)
{
data.data.Remove(this[name]);
}
/// <summary>
/// 修改账号
/// </summary>
/// <param name="name">需要修改的账号名字</param>
/// <param name="account1">需要修改成的账号信息</param>
private void ReviseAccount(string name, Account account)
{
this[name] = account;
}
/// <summary>
/// 查找账号
/// </summary>
/// <param name="name">需要查找的账号名字</param>
/// <returns>返回查看到的账号信息</returns>
private Account GetAccount(string name)
{
return this[name];
}
/// <summary>
/// 获得所有账号
/// </summary>
/// <returns>返回所有账号数组</returns>
private List<Account> GetAllAccount()
{
return data.data;
}
//--------------------检测账号部分--------------------//
/// <summary>
/// 判断是否存在该名字的账号
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public bool IsName(string key)
{
foreach (var item in data.data)
{
if (key == item.Name)
{
return true;
}
}
return false;
}
/// <summary>
/// 检测该账号密码是否正确
/// </summary>
/// <param name="name">需要检测的账号</param>
/// <param name="password">需要检测的密码</param>
/// <returns>返回是否正确</returns>
public bool IsPassword(string name,string password)
{
if (IsName(name))
{
if(GetAccount(name).Password == password)
{
return true;
}
return false;
}
return false;
}
//--------------------封装部分--------------------//
/// <summary>
/// 索引器
/// </summary>
/// <param name="name">需要查找的账号名字</param>
/// <returns>返回查找的账号名字</returns>
private Account this[string name]
{
get
{
foreach (var item in data.data)
{
if (item.Name == name)
{
return item;
}
}
return new Account();
}
set
{
for (int i = 0; i < data.data.Count; i++)
{
if(data.data[i].Name == name)
{
data.data[i] = value;
}
}
LoginEventHandler.CallSavaData(data);
}
}
}
using UnityEngine;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
/// <summary>
/// 登录注册系统事件管理类
/// </summary>
public class LoginEventSystem : MonoBehaviour
{
/// <summary>
/// 定义游戏保存数据路径
/// </summary>
private static string savaGameDataPath;
/// <summary>
/// 定义保存数据到本地的文件所在的文件夹名字
/// </summary>
private const string savaGameDataFileName = "Login_Data";
//当游戏开始时将数据保存方法与数据加载方法添加到事件中心的事件当中
private void OnEnable()
{
LoginEventHandler.SavaData += SavaData;
LoginEventHandler.LoadData += LoadData;
}
//当对象被禁用或者销毁时将事件中心中添加的事件对应移除
private void OnDisable()
{
LoginEventHandler.SavaData -= SavaData;
LoginEventHandler.LoadData -= LoadData;
}
/// <summary>
/// 初始化
/// </summary>
private void Awake()
{
//PS:Application.persistentDataPath获得的是unity游戏数据文件夹的路径
savaGameDataPath = Application.persistentDataPath;
//debug打印保存数据的路径
Debug.Log(savaGameDataPath);
}
/// <summary>
/// 负责保存数据 (事件)
/// </summary>
/// <param name="data">需要保存的数据</param>
private void SavaData(AccountData data)
{
//检测是否存在该文件夹
if (!Directory.Exists(savaGameDataPath + "/" + savaGameDataFileName))
{
//如果没有该文件夹则在该路径下创建一个名为login_Data的文件夹
Directory.CreateDirectory(savaGameDataPath + "/" + savaGameDataFileName);
}
//使用file静态方法Create在login_Data文件夹下创建一个名为data的txt文件 并且将返回对象存入变量以便后续操作
using (FileStream file = File.Create(savaGameDataPath + "/" + savaGameDataFileName + "/data.txt"))
{
//二进制转化 该对象主要用于二进制转化操作(用于加密)
BinaryFormatter formatter = new BinaryFormatter();
//使用JsonUtility静态方法ToJson将类(Data)数据转换为Json格式并返回为一个字符串
string json = JsonUtility.ToJson(data);
//使用formatter实例方法Serialize(序列化)将json字符串导入file文件中
formatter.Serialize(file, json);
}
}
/// <summary>
/// 负责加载数据 (事件)
/// </summary>
/// <returns>返回加载的数据</returns>
private AccountData LoadData()
{
//临时变量,用于保存读取的游戏数据
AccountData data = new AccountData();
//检测是否存在该文件
if (File.Exists(savaGameDataPath + "/" + savaGameDataFileName + "/data.txt"))
{
//使用File静态方法Open读取保存在本地的数据文件
using (FileStream file = File.Open(savaGameDataPath + "/" + savaGameDataFileName + "/data.txt", FileMode.Open))
{
//二进制转化 该对象主要用于二进制转化操作(用于解密)
BinaryFormatter formatter = new BinaryFormatter();
//使用formatter实例方法Deserialize(反序列化)将文件的二进制数据转换成Json文本并把Json文本返回成一个字符串
string json = (string)formatter.Deserialize(file);
//使用JsonUtility静态方法FromJsonOverwrite将Json文本的数据写入data中
JsonUtility.FromJsonOverwrite(json, data);
}
}
//如果不存在账号数据文件,则创建一个初始账号
else
{
data = new AccountData();
data.data.Add(new Account()
{
Name = "Admin",
Password = "123456",
Value = 12356
});
}
//返回数据
return data;
}
}
using System;
/// <summary>
/// 事件中心
/// </summary>
public static class LoginEventHandler
{
/// <summary>
/// 保存游戏数据到本地
/// </summary>
public static event Action<AccountData> SavaData;
/// <summary>
/// 需要保存数据时调用
/// </summary>
/// <param name="data">需要保存本地的数据</param>
public static void CallSavaData(AccountData data)
{
SavaData?.Invoke(data);
}
/// <summary>
/// 读取本地数据到游戏
/// </summary>
public static event Func<AccountData> LoadData;
/// <summary>
/// 需要加载本地数据时调用
/// </summary>
/// <returns>返回本地保存的游戏数据</returns>
public static AccountData CallLoadData()
{
return LoadData?.Invoke();
}
}
using System.Collections.Generic;
/// <summary>
/// 账号数据 (保存所有账号的数据信息)
/// </summary>
[System.Serializable]
public class AccountData
{
/// <summary>
/// 所有的数据保存在列表里
/// </summary>
public List<Account> data = new List<Account>();
}
/// <summary>
/// 账号信息
/// </summary>
[System.Serializable]
public class Account
{
/// <summary>
/// 账号名字
/// </summary>
public string Name;
/// <summary>
/// 账号密码
/// </summary>
public string Password;
/// <summary>
/// 账号需要保存的数据
/// </summary>
public int Value;
}
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 排行榜类
/// </summary>
public class Rankings : MonoBehaviour
{
[SerializeField]
//保存所有账号的名字
private List<string> accountsName;
//排行榜的显示文本
private TMPro.TMP_Text text;
//保存数据库实例
private DataBase dataBase;
//当对象被激活时调用一次
private void OnEnable()
{
//获得管理类的数据库实例
dataBase = LoginManager.Instance.dataBase;
//将文本框文本清空
text.text = string.Empty;
//获得所有账号的名字
accountsName = dataBase.GetAllAccountName();
//获得排序后的账号列表
accountsName = SortList(accountsName);
UpdateView(accountsName);
}
private void Awake()
{
text = transform.GetChild(0).GetChild(2).GetComponent<TMPro.TMP_Text>();
}
/// <summary>
/// 直接插入算法
/// </summary>
/// <param name="list">需要排序的列表</param>
public List<string> SortList(List<string> list)
{
//首先从第二个元素开始遍历
for (int i = 1; i < list.Count; i++)
{
string value = list[i];
bool isMin = true;
//让 i 下标前的全部数据和 i下标数据进行比较
for (int j = i - 1; j >= 0; j--)
{
if (dataBase.GetAccountValue(list[j]) < dataBase.GetAccountValue(value))//只要比i下标数据大就向后移一位下标,
{
list[j + 1] = list[j];
}
else//如果比i下标数据小或者相等,那么就把i下标数据赋值到他后面
{
list[j + 1] = value;
isMin = false;
break;//这里需要跳出循环,因为前面的值都是比i下标数据小
}
}
if (isMin)//如果遍历完了,前面的数据都比我大,那i下标数据就到第一个位置去
{
list[0] = value;
}
}
return list;
}
public void UpdateView(List<string> list)
{
for (int i = 0; i < list.Count; i++)
{
//显示分数前十的玩家
if (i < 10)
{
text.text += "第" + (i+1) + "名 玩家:" + list[i] + " 分数:" + dataBase.GetAccountValue(list[i]) + "\n";
}
else
{
break;
}
}
string name = PlayerPrefs.GetString("csName", "null");
for (int i = 0; i < list.Count; i++)
{
if (name == "null")
{
text.text += "你目前还未登录,无法查询到排行;";
break;
}
if (list[i] == name)
{
text.text += "你当前排名:" + (i+1) + " (玩家:" + list[i] + ")";
}
}
}
}
using UnityEngine;
using TMPro;
/// <summary>
/// 对话框类
/// </summary>
public class PromptBox : MonoBehaviour
{
//显示框显示的文本
private TMP_Text text;
//获得场景中对象的组件给变量赋值
private void Awake()
{
text = transform.GetChild(0).transform.GetChild(0).GetComponent<TMP_Text>();
}
//显示对话框以及显示文字
public void ShowBox(string showText)
{
this.gameObject.SetActive(true);
text.text = showText;
}
//动画结束时调用的函数
public void End()
{
this.gameObject.SetActive(false);
}
}

