对于Unity Sqlite和JSON 本地数据存储这方面我不是很了解,所以就在这共享一下被人的帖子,希望可以对这方面有需求的人是一种帮助。
基本思路,游戏基础配置数据,比如怪物的属性、装备模板属性、关卡怪物等,使用SQLite(Unity插件SQLiteUnityKit-GitHub地址,推荐客户端SQLite Expert Personal 3),管理方便玩家核心数据(属性、装备、技能)使用JSON格式,加密保存在Application.persistentDataPath路径里,避免每次升级被覆盖
插件本地下载地址Sqlite框架
litJson
准备工作
1 litJson.dll放在Plugins目录下
2 libsqlite3.so文件放到 Assets/Plugins/Android目录下
3 自定义的SQLite DB数据文件放到 Assets/StreamingAssets目录下
SQLite篇 将准备好的DB数据文件拷贝到Assets/StreamingAssets把SQLiteUnityKit GitHub下载的压缩包里的 DataTable.cs、SqliteDatabase.cs,拷贝到项目中的任意位置
最终项目结构看起来是这样子的
调用方式
SqliteDatabase sqlDB = new SqliteDatabase(“config.db”);string query = “INSERT INTO User(UserName) VALUES( ‘Santiago’)”;
sqlDB.ExecuteNonQuery(query);
我做了个unitypackge的例子,大家可以下载导入Json篇原先是使用XML格式来存储数据的,因为XML跨平台,但是Json同样也可以做到,加上有LitJson这个格式转化利器,因此,本地文件存储格式,本文以Json为例。
关于数据加密使用c#提供的加密类即可,自己定义秘钥
- using System.Security.Cryptography;
- using System.Text;
- public class GlobalDataHelper
- {
- private const string DATA_ENCRYPT_KEY = "a234857890654c3678d77234567890O2";
- private static RijndaelManaged _encryptAlgorithm = null;
- public static RijndaelManaged DataEncryptAlgorithm ()
- {
- _encryptAlgorithm = new RijndaelManaged ();
- _encryptAlgorithm.Key = Encoding.UTF8.GetBytes (DATA_ENCRYPT_KEY);
- _encryptAlgorithm.Mode = CipherMode.ECB;
- _encryptAlgorithm.Padding = PaddingMode.PKCS7;
- return _encryptAlgorithm;
- }
- }
SystemInfo.deviceUniqueIdentifier
本例子是以基础配置数据为例,因此代码中不提供该功能。
关于避免更新之后,玩家存档被覆盖Unity提供了一个只读路径,放在该路径下的文件,不会被软件更新所影响。
Application.persistentDataPathJson Helper类~~
- using System.Security.Cryptography;
- using System.Text;
- using System;
- using System.IO;
- using LitJson;
- public class DataStoreProcessor
- {
- private static DataStoreProcessor _dataStoreProcessor = null;
- public static DataStoreProcessor SharedInstance {
- get {
- if (_dataStoreProcessor == null)
- _dataStoreProcessor = new DataStoreProcessor ();
- return _dataStoreProcessor;
- }
- }
- /// <summary>
- /// 加密数据
- /// </summary>
- /// <returns>The data.</returns>
- /// <param name="dataToEncrypt">Data to encrypt.</param>
- public string EncryptData (string dataToEncrypt)
- {
- //给明文加密用GetBytes
- byte[] dataToEncryptArray = Encoding.UTF8.GetBytes (dataToEncrypt);
- byte[] dataAfterEncryptArray = GlobalDataHelper.DataEncryptAlgorithm().CreateEncryptor ()
- .TransformFinalBlock (dataToEncryptArray, 0, dataToEncryptArray.Length);
- return Convert.ToBase64String (dataAfterEncryptArray, 0, dataAfterEncryptArray.Length);
- }
- /// <summary>
- /// 解密数据
- /// </summary>
- /// <returns>The data.</returns>
- /// <param name="dataToDecrypt">Data to decrypt.</param>
- public string DecryptData (string dataToDecrypt)
- {
- //给密文解密用FromBase64String
- byte[] dataToDecryptArray = Convert.FromBase64String (dataToDecrypt);
- byte[] dataAfterDecryptArray = GlobalDataHelper.DataEncryptAlgorithm().CreateDecryptor ()
- .TransformFinalBlock (dataToDecryptArray, 0, dataToDecryptArray.Length);
- return Encoding.UTF8.GetString (dataAfterDecryptArray);
- }
- /// <summary>
- /// 数据保存
- /// </summary>
- /// <param name="tobject">Tobject.</param>
- /// <param name="path">;Path.</param>
- /// <typeparam name="T">The 1st type parameter.</typeparam>
- public void Save (Object tobject, string path, bool isEncrypt=true)
- {
- string serializedString = JsonMapper.ToJson (tobject);
- using (StreamWriter sw = File.CreateText(path)) {
- if (isEncrypt)
- sw.Write (EncryptData (serializedString));
- else
- sw.Write (serializedString);
- }
- }
- /// <summary>
- /// 载入数据
- /// </summary>
- /// <param name="path">;Path.</param>
- /// <typeparam name="T">The 1st type parameter.</typeparam>
- public T Load<T> (string path, bool isEncrypt=true)
- {
- if (File.Exists (path) == false)
- return default(T);
- using (StreamReader sr = File.OpenText(path)) {
- string stringEncrypt = sr.ReadToEnd ();
- if (string.IsNullOrEmpty (stringEncrypt))
- return default(T);
- if (isEncrypt)
- return JsonMapper.ToObject<T> (DecryptData (stringEncrypt));
- else
- return JsonMapper.ToObject<T> (stringEncrypt);
- }
- }
- }
调用方式 下面的代码将提供了一个自定义窗体,允许开发者自行定义用户在等待界面时,显示本地配置好的文字
按照道理,这种游戏基础配置类的应该使用Sql方式来进行数据交互,本文仅仅是为了进行功能的演示。
只有玩家数据,才使用本地文件存储的方式,存储在永久的路径里面- using UnityEngine;
- using System.Collections.Generic;
- using UnityEditor;
- public class LoadingDataConfigWindow : ScriptableWizard
- {
- public List<string> NotifyString;
- //改成 Application.persistentDataPath永久存储
- private readonly string LOADING_DATA_CONFIG_URL = Application.dataPath + @"/Resources/Setting/LoadNotify.data";
- public LoadingDataConfigWindow()
- {
- NotifyString = DataStoreProcessor.SharedInstance.Load<List<string>>(LOADING_DATA_CONFIG_URL,false);
- }
- [MenuItem ("GameObject/Data Setting/Loading text")]
- static void CreateWizard ()
- {
- LoadingDataConfigWindow window = DisplayWizard<LoadingDataConfigWindow> ("配置登陆提示文字", "确认", "取消");
- window.minSize = new Vector2(1024,768);
- }
- // This is called when the user clicks on the Create button.
- void OnWizardCreate ()
- {
- DataStoreProcessor.SharedInstance.Save(NotifyString,LOADING_DATA_CONFIG_URL,false);
- Debug.Log(string.Format(" 保存成功,共计录入 {0} 数据",NotifyString.Count));
- }
- // Allows you to provide an action when the user clicks on the
- // other button "Apply".
- void OnWizardOtherButton ()
- {
- Debug.Log ("取消");
- }
- }