我的框架-Unity3d的用户数据储存模块UserDB
前言:
我们在开发一些小游戏的时候,不可能将所有的数据都上传到服务器里去储存,有很多数据是需要储存到用户本地的。比如一些简单的用户设置,一些只需要打开一次的用户提示记录等等。当所需储存的数据比较少的时候,我们可以直接用PlayerPrefs.SetString直接来储存,但是这种方式每变化一次就需要执行一次逻辑写一行代码,而且储存的东西稍微多一点之后key就多了,对自己,对多人协同开发都是很麻烦的一件事。因此我们引入一套用户的储存类去储存用户数据,将用户的数据通过序列化的方式以json的格式储存在用户本地。接下来就是正文,我们将详细介绍。
正文:
首先我们创建三个脚本:
DBManager(继承自Unity的MonoBehaviour类,主要用于储存因为需要用到Unity的生命周期函数)
DBUser(用户储存的主类,包括创建、读取、储存等方法)
UserData(用于储存用户数据的结构体,我们就是通过序列化这个类来储存数据)
第一步:先编写一些DBUser的逻辑,上代码:
-
public class DB_User
-
{
-
-
private static DB_User _inst;
-
public static DB_User Inst
-
{
-
get { return _inst; }
-
private set { _inst = value; }
-
}
-
-
-
private string savePath = string.Empty;
-
-
public DBManager dbManager;
-
-
//构造函数
-
public DB_User()
-
{
-
_inst = this;
-
InitDB();
-
dbManager = new GameObject("DB").AddComponent<DBManager>();
-
}
-
-
private void InitDB()
-
{
-
CreateDBForder();
-
}
-
-
private void CreateDBForder()
-
{
-
string localPath = $"file://{Application.persistentDataPath}";
-
savePath = localPath "/gameDB/";
-
try
-
{
-
if (Directory.Exists(savePath) == false)
-
{
-
Directory.CreateDirectory(savePath);
-
}
-
}
-
catch { }
-
}
-
}
这里主要就是完成DB的初始化问题,包括创建储存的文件路径,以及实例出DBManager。我们需要在游戏启动时在适当的时候实例出DBUser即可。
-
private void Start()
-
{
-
new DBUser();
-
}
第二部:完成我们的UserData类。直接上代码:
-
using Newtonsoft.Json;
-
using System;
-
using System.Collections;
-
using System.Collections.Generic;
-
using UnityEngine;
-
-
public class UserData
-
{
-
public static string type = "userdata";
-
-
[]
-
public bool save = false;
-
-
-
private static UserData _inst;
-
public static UserData Inst
-
{
-
get { return _inst; }
-
set { _inst = value; }
-
}
-
-
-
-
public void InitUserData()
-
{
-
//TODO : 执行一些新用户需要执行的方法
-
}
-
-
public string ToJson()
-
{
-
string str = string.Empty;
-
str = JsonConvert.SerializeObject(this, Formatting.None);
-
return str;
-
}
-
-
public UserData() { }
-
-
-
-
private int _glod = 2000;
-
-
//******************************************************************************//
-
//******** 注意:增加字段,一定要【设默认值】且数组【不能赋值】 **********//
-
//******** 增加字段,private, 不要直接增加public **********//
-
//******** 按照当前的标准处理.否则可能无法存储 **********//
-
//******************************************************************************//
-
-
//用户的金币数量
-
public int glod { get { return _glod; } set { _glod = value; save = true; } }
-
}
稍微解释下:
string type这个变量主要是区分储存的类型的,这里是"userdata"主要就是本地储存用户数据的,将来可能还有数据库储存的类型,这里就不展开说了,本文只介绍本地储存。觉着没用的把它删了就行,其他脚本里用到相关类型的一起改一下就好,觉得麻烦的就留着也没有什么影响。
至于这个bool save这个变量主要是控制是否需要储存的,我们每次修改值也就是Set的时候将save设为true,这样在每次保存数据的时候如果没有值的改变我们就不需要储存数据,这是提升性能的一个小技巧。
ToJson这个方法就是将这个类序列化,返回一个字符串,这里我用的是Newtonsoft.Json。大家自己在github上找吧,我这里就不贴了。
我们这里不仅可储存int、string、bool等基础类型,也可以储存List、Dictionary等数组、字典。也可以自己创建结构体去储存。可以说扩展性非常的强。
第三部:有了我们的数据储存类,就继续完成我们的DBUser的读取与储存逻辑:
-
public class DB_User
-
{
-
-
private static DB_User _inst;
-
public static DB_User Inst
-
{
-
get { return _inst; }
-
private set { _inst = value; }
-
}
-
-
-
private const string PLAYKEY = "db_";
-
-
private string savePath = string.Empty;
-
-
public DBManager dbManager;
-
-
public DB_User()
-
{
-
_inst = this;
-
InitDB();
-
dbManager = new GameObject("DB").AddComponent<DBManager>();
-
}
-
-
public void SaveUser()
-
{
-
string queryModel = UserData.Inst.ToJson();
-
Save(queryModel, UserData.type);
-
}
-
-
private void InitDB()
-
{
-
CreateDBForder();
-
-
InitUserdata();
-
}
-
-
private void CreateDBForder()
-
{
-
string localPath = $"file://{Application.persistentDataPath}";
-
savePath = localPath "/gameDB/";
-
try
-
{
-
if (Directory.Exists(savePath) == false)
-
{
-
Directory.CreateDirectory(savePath);
-
}
-
}
-
catch { }
-
}
-
-
private void InitUserdata()
-
{
-
string queryModel = Read(UserData.type);
-
Debug.Log("UserData : " queryModel);
-
if (!string.IsNullOrEmpty(queryModel))
-
{
-
UserData.Inst = JsonConvert.DeserializeObject<UserData>(queryModel);
-
}
-
else
-
{
-
// 无数据就创建新用户
-
UserData.Inst = new UserData();
-
UserData.Inst.InitUserData();
-
}
-
}
-
-
private string Read(string type)
-
{
-
string data = string.Empty;
-
string name = PLAYKEY type ".dat";
-
string filename = string.Format("{0}/{1}", savePath, name);
-
if (FileExists(filename))
-
{
-
try
-
{
-
data = StreamReader(filename);
-
}
-
catch
-
{
-
Debug.LogError("存档文件失败 : " filename);
-
}
-
}
-
return data;
-
}
-
-
private void Save(string data, string type)
-
{
-
string name = PLAYKEY type ".dat";
-
try
-
{
-
string filename = string.Format("{0}/{1}", savePath, name);
-
StreamWriter(filename, data);
-
}
-
catch
-
{
-
Debug.LogError("存档文件保存失败:" name);
-
}
-
}
-
-
-
/// <summary>
-
/// 判断文件是否存在
-
/// </summary>
-
/// <param name="path"></param>
-
/// <returns></returns>
-
private bool FileExists(string path)
-
{
-
path = ReplaceFileStart(path);
-
return System.IO.File.Exists(path);
-
}
-
-
/// <summary>
-
/// 替换FILE
-
/// </summary>
-
/// <param name="path"></param>
-
/// <returns></returns>
-
private string ReplaceFileStart(string path)
-
{
-
if (path.StartsWith("file://"))
-
{
-
path = path.Replace("file://", string.Empty);
-
}
-
return path;
-
}
-
-
/// <summary>
-
/// 读取文件
-
/// </summary>
-
/// <param name="path"></param>
-
/// <returns></returns>
-
private string StreamReader(string path)
-
{
-
path = ReplaceFileStart(path);
-
if (FileExists(path))
-
{
-
try
-
{
-
System.IO.StreamReader sr = new System.IO.StreamReader(path);
-
string jsonStr = sr.ReadToEnd();
-
sr.Close();
-
return jsonStr;
-
}
-
catch
-
{
-
Debug.LogError("读取文件失败 : " path);
-
}
-
}
-
return string.Empty;
-
}
-
-
/// <summary>
-
/// 写入储存文件
-
/// </summary>
-
/// <param name="path"></param>
-
/// <param name="data"></param>
-
private void StreamWriter(string path, string data)
-
{
-
path = ReplaceFileStart(path);
-
try
-
{
-
string forder = GetFileDirectory(path);
-
bool exists = System.IO.Directory.Exists(forder);
-
if (!exists)
-
{
-
System.IO.Directory.CreateDirectory(forder);
-
}
-
-
System.IO.StreamWriter sw = new System.IO.StreamWriter(path);
-
sw.Write(data);
-
//关闭StreamWriter
-
sw.Close();
-
}
-
catch (System.Exception ee)
-
{
-
Debug.Log("文件写入失败:" path " Error:" ee.Message);
-
}
-
}
-
-
/// <summary>
-
/// 替换格式
-
/// </summary>
-
/// <param name="path"></param>
-
/// <returns></returns>
-
private string GetFileDirectory(string path)
-
{
-
path = path.Replace("\\", "/");
-
path = ReplaceFileStart(path);
-
return System.IO.Path.GetDirectoryName(path);
-
}
-
-
}
(数据加密这里我就不展开说了,这里只介绍储存方法)
最后就是处理DBManager了 :
-
using System.Collections;
-
using System.Collections.Generic;
-
using UnityEngine;
-
-
public class DBManager : MonoBehaviour
-
{
-
private float saveTimeout = 0;
-
-
/// <summary>
-
/// 用户数据自动储存时间
-
/// </summary>
-
public const float AUTOSAVETIME = 60f;
-
-
private void Start()
-
{
-
DontDestroyOnLoad(this);
-
}
-
-
private void Update()
-
{
-
AutoSave();
-
}
-
-
private void OnApplicationFocus(bool focus)
-
{
-
if (!focus)
-
{
-
SaveData();
-
}
-
}
-
-
private void SaveData()
-
{
-
if (UserData.Inst == null || DB_User.Inst == null) return;
-
-
if (UserData.Inst.save)
-
{
-
DB_User.Inst.SaveUser();
-
UserData.Inst.save = false;
-
}
-
}
-
-
private void AutoSave()
-
{
-
if (Time.time > saveTimeout AUTOSAVETIME)
-
{
-
saveTimeout = Time.time;
-
SaveData();
-
}
-
}
-
}
这里就是每隔60s对用户数据进行一次本地的写入储存,如果用户有脱离游戏焦点的行为是强制储存一次。
结尾:
如何使用我们这个数据储存模块呢?
在正确的初始化之后,我们直接调用UserData就可以了。
UserData.Inst.glod = 100;
再次进入游戏之后就可看到在控台输出一个json:
-
{
-
"glod": 96010
-
}
这篇好文章是转载于:学新通技术网
- 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
- 本站站名: 学新通技术网
- 本文地址: /boutique/detail/tanhfichfa
-
photoshop保存的图片太大微信发不了怎么办
PHP中文网 06-15 -
Android 11 保存文件到外部存储,并分享文件
Luke 10-12 -
word里面弄一个表格后上面的标题会跑到下面怎么办
PHP中文网 06-20 -
《学习通》视频自动暂停处理方法
HelloWorld317 07-05 -
微信公众号没有声音提示怎么办
PHP中文网 03-31 -
photoshop扩展功能面板显示灰色怎么办
PHP中文网 06-14 -
excel下划线不显示怎么办
PHP中文网 06-23 -
怎样阻止微信小程序自动打开
PHP中文网 06-13 -
excel打印预览压线压字怎么办
PHP中文网 06-22 -
photoshop蒙版画笔没反应怎么办
PHP中文网 06-24