# 路径助手
- 分平台处理 StreamingAssets 路径
- Application.streamingAssetsPath 会根据不同的平台返回对应的 StreamingAssets 目录,这是最常用的方法,也可以使用 Unity 宏标签手动分平台,在下面的代码中会做出演示。
- 只有 PC 端的 StreamingAssets 文件夹是可读写的,其他平台都是只读的(.txt 文件可以直接读,其他类型的文件需要进一步操作)。
- 移动端(Android、iOS 等):想要读写这些文件,需要将 StreamingAssets 文件夹中的内容拷贝到持久化路径 Application.persistentDataPath(Unity 外部目录),这个路径可以在运行时进行读写操作。
- Web 端:无法写入。
- 注意:如果 StreamingAssets 下的文件很多,应该单独处理他们(例:在第一次进入游戏时完成文件的复制、在游戏的加载场景(过渡场景、动画等)中完成文件的复制)
按需加载
using System; | |
using System.IO; | |
using UnityEngine; | |
using UnityEngine.Networking; | |
namespace Common | |
{ | |
/// <summary> | |
/// 路径助手(按需加载) | |
/// </summary> | |
public class PathHelper | |
{ | |
/// <summary> | |
/// 手动分平台处理 StreamingAssets 路径 | |
/// </summary> | |
/// <param name="path">StreamingAssets 中的路径 & lt;/param> | |
/// <returns></returns> | |
[Obsolete("Use GetPath instead", true)] | |
public static string HandlePath(string path) | |
{ | |
string localPath; | |
#region 分平台判断路径 | |
// 这样写 性能不好 | |
//if (Application.platform == RuntimePlatform.Android) | |
//{ | |
// localPath = Application.streamingAssetsPath + "/" + path; | |
//} | |
//else | |
//{ | |
// localPath = "file://" + Application.streamingAssetsPath + "/" + path; | |
//} | |
// 性能更高的写法,使用 Unity 宏标签 | |
// 不同的平台会拥有不同的代码(如果发布到安卓平台,就只有第三段代码,其他的代码不会打包带走) | |
//Application.dataPath 会定位到 Assets 目录 | |
//Application.streamingAssetsPath 会根据不同的平台返回对应的 StreamingAssets 目录,一般情况下使用这个即可 | |
#if UNITY_EDITOR || UNITY_STANDALONE | |
localPath = "file://" + Application.dataPath + "/StreamingAssets/" + path; | |
#elif UNITY_IOS | |
localPath = "file://" + Application.dataPath + "/Raw/" + path; | |
#elif UNITY_ANDROID | |
localPath = "jar:file://" + Application.dataPath + "!/assets/" + path; | |
#else | |
localPath = "file://" + Application.streamingAssetsPath + "/" + path; | |
#endif | |
#endregion | |
return localPath; | |
} | |
/// <summary> | |
/// 分平台处理 StreamingAssets 路径 | |
/// </summary> | |
/// <param name="path">StreamingAssets 中的路径 & lt;/param> | |
/// <returns></returns> | |
public static string GetPath(string path) | |
{ | |
#if UNITY_ANDROID || UNITY_IOS | |
string resPath = Application.persistentDataPath + path; | |
if (!File.Exists(resPath)) | |
{ | |
CopyFile(path); | |
} | |
return resPath; | |
#else | |
return Application.streamingAssetsPath + path; | |
#endif | |
} | |
/// <summary> | |
/// 将 StreamingAssets 中的文件拷贝到持久化路径中 path=StreamingAssets 中的路径 | |
/// </summary> | |
private static void CopyFile(string path) | |
{ | |
// 获取 StreamingAssets 路径 | |
// 创建 UnityWebRequest 对象 | |
UnityWebRequest www = UnityWebRequest.Get(Application.streamingAssetsPath + path); | |
// 发送请求并等待返回 | |
// 如果不是静态方法,可以使用协程,但是协程会影响其他方法的调用,所以不建议使用 | |
//yield return www.SendWebRequest(); | |
www.SendWebRequest(); | |
while (!www.isDone) { } | |
if (www.result != UnityWebRequest.Result.Success) | |
{ | |
Debug.LogError("拷贝文件出错:" + www.error); | |
} | |
else | |
{ | |
// 创建路径(如果不存在) | |
Directory.CreateDirectory(Application.persistentDataPath + path.Substring(path.IndexOf('/'), path.LastIndexOf('/'))); | |
// 写入文件 | |
File.WriteAllBytes(Application.persistentDataPath + path, www.downloadHandler.data); | |
} | |
} | |
} | |
} |
优先全部加载(单例模式)
using System.Collections; | |
using System.IO; | |
using System.Linq; | |
using UnityEngine; | |
using UnityEngine.Networking; | |
namespace Common | |
{ | |
/// <summary> | |
/// 路径助手(优先全部加载) | |
/// </summary> | |
public class PathHelperPriority : MonoSingleton<PathHelperPriority> | |
{ | |
protected override void Init() | |
{ | |
base.Init(); | |
#if UNITY_ANDROID || UNITY_IOS | |
StartCoroutine(GetFilePath()); | |
#else | |
return; | |
#endif | |
} | |
/// <summary> | |
/// 分平台处理 StreamingAssets 路径 | |
/// </summary> | |
/// <param name="path">StreamingAssets 中的路径 & lt;/param> | |
/// <returns></returns> | |
public string GetPath(string path) | |
{ | |
#if UNITY_ANDROID || UNITY_IOS | |
return Application.persistentDataPath + path; | |
#else | |
return Application.streamingAssetsPath + path; | |
#endif | |
} | |
/// <summary> | |
/// 获取 StreamingAssets 中所有文件路径 | |
/// </summary> | |
private IEnumerator GetFilePath() | |
{ | |
string sourcePath = Application.streamingAssetsPath; | |
string destinationPath = Application.persistentDataPath; | |
// 选取需要拷贝的文件 | |
string[] filePaths = Directory.GetFiles(sourcePath, "*", SearchOption.AllDirectories). | |
Where( | |
file => file.EndsWith(".txt") || | |
file.EndsWith(".xml") || | |
file.EndsWith(".db")). | |
ToArray(); | |
foreach (string filePath in filePaths) | |
{ | |
string relativePath = filePath.Substring(sourcePath.Length).Replace("\\", "/"); | |
string destFilePath = destinationPath + relativePath; | |
// 如果文件已存在,则跳过 | |
if (File.Exists(destFilePath)) continue; | |
yield return CopyFile(relativePath); | |
} | |
} | |
/// <summary> | |
/// 将 StreamingAssets 中的文件拷贝到持久化路径中 path=StreamingAssets 中的路径 | |
/// </summary> | |
private IEnumerator CopyFile(string path) | |
{ | |
// 获取 StreamingAssets 路径 | |
// 创建 UnityWebRequest 对象 | |
UnityWebRequest www = UnityWebRequest.Get(Application.streamingAssetsPath + path); | |
// 发送请求并等待返回 | |
yield return www.SendWebRequest(); | |
if (www.result != UnityWebRequest.Result.Success) | |
{ | |
Debug.LogError("拷贝文件出错:" + www.error); | |
} | |
else | |
{ | |
// 创建路径(如果不存在) | |
Directory.CreateDirectory(Application.persistentDataPath + path.Substring(path.IndexOf('/'), path.LastIndexOf('/'))); | |
// 写入文件 | |
File.WriteAllBytes(Application.persistentDataPath + path, www.downloadHandler.data); | |
} | |
} | |
} | |
} |