一, persistentDataPath的意义
我们知道Unity提供了一个StreamingAssets的文件夹(在Assets中,没有请自己创建),此目录的特点是:只能读,不能写.所以在应对某些需要写入操作的时候,就显得有些尴尬了. 所有Unity又提供了一个特殊的文件夹:persistentDataPath,可读可写(所在,有人也称之为:持久化路径).但是,此文件夹和StreamingAssets还有一个不同点:在Editor阶段是没有的, 等到手机安装App会自动生成.
二, 使用原则
1, 可以将一些需要可写的文件先放在StreamingAssets,在App安装的时候Copy到persistentDataPath文件夹
2, 可以在persistentDataPath文件夹中存储一些玩家的本地数据.
三, 实践(Demo)
1, 用StreamingAseets里面的ResourcesMap.txt为例, 将他Copy到persistentDataPath文件夹下
public void copy(string fileName = "ResouresMap.txt")
{
string url;//文件源
#if UNITY_EDITOR || UNITY_STANDALONE //独立的平台(Mac,Windows或Linux)
url = $"file://{Application.dataPath}/StreamingAssets/{fileName}";
#elif UNITY_IPHONE
url = $"file://{Application.dataPath}/Raw/{fileName}";
#elif UNITY_ANDROID
url = $"jar:file://{Application.dataPath}!/assets/{fileName}";
#endif
string persistentUrl = $"{Application.persistentDataPath }/{fileName}";//持久化地址
if (!File.Exists(persistentUrl))
{
Debug.Log($"{persistentUrl} 文件不存在,需要从StreamingAssets中Copy!");
WWW www = new WWW(url);
while (true)
{
if (www.isDone)
{
if (www.error == null)
{
File.WriteAllText(persistentUrl, www.text);//本次读的是文本 File.WriteAllBytes(path, www.bytes);
Debug.Log($"持久化目录: {persistentUrl}");
break;
}
else
{
Debug.LogWarning($"没有得到StreamingAssets里面的文件 : {fileName}");
}
}
}
}
else
{
Debug.Log($"{persistentUrl} 文件已经存在!");
}
}
结果:
1.1, PC上的
这是PC上的persistentDataPath路径.
1.2 Android上的
并且在Android的持久化路径下确实存在 ResourcesMap.txt
2, 在本地存储一些玩家数据
/// <summary>
/// 本地数据键值对
/// </summary>
private Dictionary<string, string> localInfoMap;
private readonly string localInfoName = "localInfo.txt";
public Copy2Persistent()
{
this.GetLocalInfo();
}
private void GetLocalInfo()
{
string persistentUrl = $"{Application.persistentDataPath}/{this.localInfoName}";//持久化地址
if (File.Exists(persistentUrl))
{
Debug.Log($"存在文件 : {persistentUrl} , 开始读取!");
string info = null;
WWW www = new WWW(persistentUrl);
while (true)
{
if (www.error == null)
{
if (www.isDone)
{
info = www.text;
break;
}
}
else
{
Debug.LogWarning($"文件 {persistentUrl} 读取失败!");
break;
}
}
if (info != null)
{
this.localInfoMap = new Dictionary<string, string>();
//开始处理键值参数
using (StringReader sr = new StringReader(info))
{
string strLine;
string[] arr;
while ((strLine = sr.ReadLine()) != null)
{
if (strLine.IndexOf('=') > 0)
{
arr = strLine.Split('=');
this.localInfoMap.Add(arr[0], arr[1]);
}
}
}
if (this.localInfoMap.Count == 0)
{
this.localInfoMap = null;
}
}
}
else
{
Debug.LogWarning($"{persistentUrl} , 不存在不能读取本地数据!");
}
}
/// <summary>
/// 持久化数据
/// </summary>
/// <param name="key">键</param>
/// <param name="info">值</param>
public void WriteLocalInfo(string key, string info)
{
string persistentUrl = $"{Application.persistentDataPath}/{this.localInfoName}";//持久化地址
if (this.localInfoMap == null)//persistentDataPath 不存在本地数据表
{
File.WriteAllLines(persistentUrl, new string[] { $"{key}={info}" });//写入一条数据
this.localInfoMap = new Dictionary<string, string>();
this.localInfoMap.Add(key, info);
Debug.Log($"新建本地数据 ${persistentUrl} , 数据: {key}={info}");
}
else
{
if (!this.localInfoMap.ContainsKey(key))
{
File.AppendAllLines(persistentUrl, new string[] { $"{key}={info}" });//添加一条新的数据到数据表
this.localInfoMap.Add(key, info);
Debug.Log($"添加本地数据 ${persistentUrl} , 数据: {key}={info}");
}
else//需要更改数据
{
string[] newStrArr = new string[this.localInfoMap.Count];
this.localInfoMap[key] = info;
int i = 0;
foreach (string item in new List<string>(this.localInfoMap.Keys))
{
newStrArr[i] = $"{item}={this.localInfoMap[item]}";
i++;
}
File.WriteAllLines(persistentUrl, newStrArr);//重新覆盖写入数据
Debug.Log($"修改本地数据 ${persistentUrl} , 数据: {key}={info}");
}
}
}
/// <summary>
/// 读取本地数据
/// </summary>
/// <param name="key">键</param>
public string ReadLocalInfoByKey(string key)
{
if (this.localInfoMap == null || !this.localInfoMap.ContainsKey(key)) return null;
return this.localInfoMap[key];
}
2.1 使用 键=值得存储格式
(把持久化路径下的ResourcesMap.txt删除)测试代码如下:
结果
2.2, PC端
持久化路径又生成了2个文件ResourcesMap.txt, localInfo.txt2个文件
2.3 在Android端
持久化路径如下:
很完美, 就是没有iOS, 暂时先这样了 ......