【Unity】上下文管理器

StreamingAssets方法

这是一个只读不可写的目录;该文件夹的资源会保持原始格式(比如图片不会被引擎进行纹理压缩),dll文件或脚本放在该文件夹下也不会参与编译

官方推荐使用Application.streamingAssetsPath来获取该文件夹的实际位置,其可规避平台差异:
对于UnityEditor,windows平台,其等价于:Application.dataPath + "/StreamingAssets"
对于macOS,其等价于:Application.dataPath+"/Resources/Data/StreamingAssets"
对于ios平台,其等价于:Application.dataPath + "/Raw";
对于android平台,其等价于:"jar:file://" + Application.dataPath + "!/assets/";

基础使用方法:

1
2
3
4
// 设置路径
string jsonPath = Application.streamingAssetsPath + @"/JSON/IP.json";
// 读取文件
string jsonStr = System.IO.File.ReadAllText(jsonPath, Encoding.UTF8);

对于非Android和WebGL平台,支持File或者Stream的读取操作
但是对于Android和WebGL平台上无法访问StreamingAssets文件夹。在WebGL上没有文件访问权。Android使用压缩的.apk文件。这些平台无法返回URL。
解决方案:

  1. 把StreamingAssets下的文件写入persistentDataPath,后续的读取和写入都在persistentDataPath进行
  2. 使用UnityWebRequest对StreamingAssets下的文件进行读取

使用UnityWebRequest读取

UnityWebRequest读取文件需要传入文件的URL,StreamingAssets目录不同平台对应的URL是不一样的,如下:

  • Window平台 file:///D:/DATA/StreamingAssets/data.json
  • WebGL平台 http://localhost/StreamingAssets/data.json
  • Android平台 jar:file:///data/app/xxx!/assets/data.json
  • IOS平台 Application/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/xxx.app/Data/Raw

这时候最好通过构造Uri()的方式来规避平台的差异,获得真正的请求URL。如:

1
var uri = new System.Uri(Path.Combine(Application.streamingAssetsPath, "data.json")).AbsoluteUri;

方法Path.Combine(Path1, Path2)在检测到path1不是以分隔符结尾的话,会自动补充分隔符


PersistentDataPath方法

该方法下的文件可读可写

使用这个方法生成的文件所在路径为:C:\Users\Administrator\AppData\LocalLow\DefaultCompany\项目名

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
using System.IO;

// 设置路径
string filePath = Path.Combine(Application.persistentDataPath, "config.json");
// 判断文件是否存在
if (!File.Exists(filePath))
{
try //如果文件不存在,创建一个新文件
{
// 创建文件并写入内容
File.WriteAllText(filePath, "{ \"settingCycle\", 999 }"));
Debug.Log("Remark file created successfully.");
}
catch (System.Exception ex) // 如果创建失败会捕获错误
{
Debug.LogError("Failed to create remark file: " + ex.Message);
}
}
// 有了前面的兜底创建文件的步骤,这一步就可以直接读取该路径下的文件了
string jsonContent = File.ReadAllText(filePath);

Resources方法

是存储资源的文件的方法,如音频、视频、预制体等
在读取文件时可以不加后缀
只可读
打包后文件夹内容会被加密,无法直接看到该文件夹下的内容

1
2
// 读取Resources文件夹下的内容
prefab = UnityEngine.Resources.Load<GameObject>("BayWindow/prefabObject");

通用方法

这种方法可以将文件存储在与Assets同级路径下
可以读取文本文件和资源文件

1
2
3
4
5
6
7
8
// 先制定好根路径
string DynamicParent = Application.dataPath + "/../资源/";
// 设置路径
string descriptionPath = "文本文件/start.text";
// 创建文件,后立刻释放相关资源
File.Create(DynamicParent + descriptionPath).Dispose();
// 读取文件
string content = File.ReadAllText(DynamicParent + descriptionPath)

拓展:在创建文件前可以先创建该文件的父级文件夹

1
2
3
4
5
6
7
8
// 获取文件的父级文件夹路径
parentPath = System.IO.Path.GetDirectoryName(DynamicParent + descriptionPath);
// 判断父级文件夹是否存在,如果不存在就创建
if (!Directory.Exists(parentPath))
Directory.CreateDirectory(parentPath)
// 判断该文件是否存在,如果不存在就创建
if (!File.Exists(DynamicParent + descriptionPath))
File.Create(DynamicParent + descriptionPath).Dispose();

Path.GetDirectoryName(path)是获取path这个路径的父文件路径,具体用法如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
string filePath = @"C:\MyDir\MySubDir\myfile.ext";
string directoryName;
int i = 0;

while (filePath != null)
{
directoryName = Path.GetDirectoryName(filePath);
Console.WriteLine("GetDirectoryName('{0}') returns '{1}'",
filePath, directoryName);
filePath = directoryName;
if (i == 1)
{
filePath = directoryName + @"\"; // this will preserve the previous path
}
i++;
}
/*
This code produces the following output:

GetDirectoryName('C:\MyDir\MySubDir\myfile.ext') returns 'C:\MyDir\MySubDir'
GetDirectoryName('C:\MyDir\MySubDir') returns 'C:\MyDir'
GetDirectoryName('C:\MyDir\') returns 'C:\MyDir'
GetDirectoryName('C:\MyDir') returns 'C:\'
GetDirectoryName('C:\') returns ''
*/

参考:

详解Unity中的StreamingAssets文件夹