unity使用的5.3版本,本打算用Easy Save 2做存取的,發現學習成本太高了。直接選了二進制存取
後續再修改
測試
IEnumerator Wait()
{
yield return null;
Game.Scene.AddComponent<ConfigureDataComponent>();
Game.Scene.AddComponent<RuntimeDataComponent>();
yield return null;
var data = Game.Scene.GetComponent<RuntimeDataComponent>().Get<Test>() as Test;
Log.Debug(data.num.ToString());
data.num = 9999;
}
數據的存取
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using UnityEngine;
namespace ETModel
{
public static class FileHelper
{
public static object Load(string path, string type)
{
if (!File.Exists(path))
return Activator.CreateInstance(Type.GetType(type));
return BytesToObject(File.ReadAllBytes(path))?? Activator.CreateInstance(Type.GetType(type));
}
public static object LoadResources(string path, string type)
{
var ta = Resources.Load<TextAsset>(path);
if (ta == null || ta.bytes.Length == 0)
return Activator.CreateInstance(Type.GetType(type));
return BytesToObject(ta.bytes)?? Activator.CreateInstance(Type.GetType(type));
}
public static void Save<T>(string path, T value)
{
var dir = Path.GetDirectoryName(path);
if (!Directory.Exists(dir))
Directory.CreateDirectory(dir);
var bytes = ObjectToBytes(value);
File.WriteAllBytes(path, bytes);
}
public static byte[] ObjectToBytes<T>(T value)
{
try
{
using (var ms = new MemoryStream())
{
IFormatter iFormatter = new BinaryFormatter();
iFormatter.Serialize(ms, value);
return ms.ToArray();
}
}
catch(Exception ex)
{
Log.Error(ex);
return null;
}
}
public static object BytesToObject(byte[] bytes)
{
try
{
using (var ms = new MemoryStream(bytes))
{
IFormatter iFormatter = new BinaryFormatter();
ms.Seek(0, SeekOrigin.Begin);
return iFormatter.Deserialize(ms);
}
}
catch(Exception ex)
{
Log.Error(ex);
return null;
}
}
public static void GetAllFiles(List<string> files, string dir)
{
string[] fls = Directory.GetFiles(dir);
foreach (string fl in fls)
{
files.Add(fl);
}
string[] subDirs = Directory.GetDirectories(dir);
foreach (string subDir in subDirs)
{
GetAllFiles(files, subDir);
}
}
public static void CleanDirectory(string dir)
{
foreach (string subdir in Directory.GetDirectories(dir))
{
Directory.Delete(subdir, true);
}
foreach (string subFile in Directory.GetFiles(dir))
{
File.Delete(subFile);
}
}
public static void CopyDirectory(string srcDir, string tgtDir)
{
DirectoryInfo source = new DirectoryInfo(srcDir);
DirectoryInfo target = new DirectoryInfo(tgtDir);
if (target.FullName.StartsWith(source.FullName, StringComparison.CurrentCultureIgnoreCase))
{
throw new Exception("父目錄不能拷貝到子目錄!");
}
if (!source.Exists)
{
return;
}
if (!target.Exists)
{
target.Create();
}
FileInfo[] files = source.GetFiles();
for (int i = 0; i < files.Length; i++)
{
File.Copy(files[i].FullName, Path.Combine(target.FullName, files[i].Name), true);
}
DirectoryInfo[] dirs = source.GetDirectories();
for (int j = 0; j < dirs.Length; j++)
{
CopyDirectory(dirs[j].FullName, Path.Combine(target.FullName, dirs[j].Name));
}
}
}
}
MD5加密
using System.IO;
using System.Security.Cryptography;
using System.Text;
namespace ETModel
{
public static class MD5Helper
{
public static string FileMD5(string filePath)
{
byte[] retVal;
using (FileStream file = new FileStream(filePath, FileMode.Open))
{
MD5 md5 = new MD5CryptoServiceProvider();
retVal = md5.ComputeHash(file);
}
return retVal.ToHex("x2");
}
public static string StringMD5(string value)
{
MD5 md5 = MD5.Create();
byte[] byteOld = Encoding.UTF8.GetBytes(value);
byte[] byteNew = md5.ComputeHash(byteOld);
StringBuilder sb = new StringBuilder();
foreach (byte b in byteNew)
{
sb.Append(b.ToString("x2"));
}
return sb.ToString();
}
}
}
Resources 文件的配置讀取
using System.Collections.Generic;
namespace ETModel
{
public interface IConfigureData
{
}
public class ConfigureDataComponent:Component
{
Dictionary<string, IConfigureData> dic = new Dictionary<string, IConfigureData>();
public void Awake()
{
var assemblie = typeof(ConfigureDataComponent).Assembly;
foreach(var type in assemblie.GetTypes())
{
if(type.GetInterface(typeof(IConfigureData).Name)!=null)
{
dic.Add(type.Name, (IConfigureData)FileHelper.LoadResources("Configure/" + type.Name,type.FullName));
}
}
}
public IConfigureData Get<T>() where T : IConfigureData
{
var key = typeof(T).Name;
if (dic.ContainsKey(key))
return dic[key];
return null;
}
}
[ObjectSystem]
public class ConfigureDataComponentAwakeSystem : AwakeSystem<ConfigureDataComponent>
{
public override void Awake(ConfigureDataComponent self)
{
self.Awake();
}
}
}
全局數據和賬號綁定數據
using System.Collections.Generic;
using UnityEngine;
namespace ETModel
{
public interface IRuntimeData
{
void Update();
}
public interface IGlobalData: IRuntimeData
{
}
public interface IAccountData: IRuntimeData
{
}
public class RuntimeDataComponent : Component
{
string uid;
Dictionary<string, IRuntimeData> dic = new Dictionary<string, IRuntimeData>();
public void Awake()
{
var assemblie = typeof(RuntimeDataComponent).Assembly;
foreach (var type in assemblie.GetTypes())
{
if (type.GetInterface(typeof(IGlobalData).Name) != null)
{
var value = (IGlobalData)FileHelper.Load(string.Format("{0}/{1}", Application.persistentDataPath,MD5Helper.StringMD5(type.Name)), type.FullName);
dic.Add(type.Name, value);
}
}
}
public void LoadAllAccountBindingData(string uid)
{
this.uid = uid;
var assemblie = typeof(RuntimeDataComponent).Assembly;
foreach (var type in assemblie.GetTypes())
{
if (type.GetInterface(typeof(IAccountData).Name) != null)
{
var value = (IAccountData)FileHelper.Load(string.Format("{0}/{1}/{2}", Application.persistentDataPath, uid, MD5Helper.StringMD5(type.Name)), type.FullName);
dic.Add(type.Name, value);
}
}
}
public IRuntimeData Get<T>()where T:IRuntimeData
{
var key = typeof(T).Name;
if (dic.ContainsKey(key))
return dic[key];
return null;
}
public void SaveAll()
{
string path;
foreach (var data in dic.Values)
{
if(data.GetType().GetInterface(typeof(IAccountData).Name)!=null)
{
path = string.Format("{0}/{1}/{2}", Application.persistentDataPath, uid, MD5Helper.StringMD5(data.GetType().Name));
}
else
{
path = string.Format("{0}/{1}", Application.persistentDataPath, MD5Helper.StringMD5(data.GetType().Name));
}
FileHelper.Save(path, data);
}
}
public void Destroy()
{
SaveAll();
}
}
[ObjectSystem]
public class RuntimeDataComponentAwakeSystem : AwakeSystem<RuntimeDataComponent>
{
public override void Awake(RuntimeDataComponent self)
{
self.Awake();
}
}
[ObjectSystem]
public class RuntimeDataComponentDestroySystem : DestroySystem<RuntimeDataComponent>
{
public override void Destroy(RuntimeDataComponent self)
{
self.Destroy();
}
}
}