unity-doc-资源热更新

注意问题

打包报错”Moving Temp/unitystream.unity3d to [path] 系统找不到指定文件”

同一个lable包里面有同样名称的资源
包里面有中文或其他非法文字

运行丢失光照贴图

运行丢失光照贴图的场景,打开Project Setting/Graphics修改场景的Lightmap ModesFog Modes都改成Custom,勾选自己需要的选项,别使用Automatic

目录

StreamingAssets

  • 在移动平台下,Application.streamingAssetsPath是只读的,不能写入数据。

  • android 下不可用 File 类来读取,只能使用www读取,为了统一建议都用www加载文件。

  • PC和IOS平台下,读取路径必须加上file://,而 android 不需要。

  • 在IOS和Android下,还能用AssetBundle.LoadFromFile来同步读取数据。

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
26
27
28
void Awake()
{
string path =
#if UNITY_ANDROID && !UNITY_EDITOR
Application.streamingAssetsPath + "/Josn/modelname.json";
#elif UNITY_IPHONE && !UNITY_EDITOR
"file://" + Application.streamingAssetsPath + "/Josn/modelname.json";
#elif UNITY_STANDLONE_WIN||UNITY_EDITOR
"file://" + Application.streamingAssetsPath + "/Josn/modelname.json";
#else
string.Empty;
#endif
StartCoroutine(ReadData(path));
}

IEnumerator ReadData(string path)
{
WWW www = new WWW(path);
yield return www;
while (www.isDone == false)
{
yield return new WaitForEndOfFrame();
}
yield return new WaitForSeconds(0.5f);
string data = www.text;
yield return new WaitForEndOfFrame();

}

ios

变量 路径
Application.dataPath /var/containers/Bundle/Application/app sandbox/xxx.app/Data
Application.streamingAssetsPath /var/containers/Bundle/Application/app sandbox/test.app/Data/Raw
Application.temporaryCachePath /var/mobile/Containers/Data/Application/app sandbox/Library/Caches
Application.persistentDataPath /var/mobile/Containers/Data/Application/app sandbox/Documents

iOSMac OS X不同于Windows,app都是在一个沙盒空间中运行,每个app也有一个独立的数据存储空间,各app彼此不能互相访问、打扰。

dataPath是app程序包安装路径,app本身就在这里,此目录是只读的。
streamingAssetsPath是dataPath下的Raw目录。

app的独立数据存储目录下有三个文件夹:Documents,Library和tmp。

  • Documents目录,这个目录用于存储需要长期保存的数据,比如我们的热更新内容就写在这里。需要注意的是,iCloud会自动备份此目录,如果此目录下写入的内容较多,审核的可能会被苹果拒掉。
  • Library目录,这个目录下有两个子目录,Caches和Preferences。
    • Caches是一个相对临时的目录,适合存放下载缓存的临时文件,空间不足时可能会被系统清除,Application.temporaryCachePath返回的就是此路径。我把热更新的临时文件写在这里,等一个版本的所有内容更新完全后,再把内容转移到Documents目录。
    • Preferences用于应用存储偏好设置,用NSUserDefaults读取或设置。
  • tmp目录,临时目录,存放应用运行时临时使用的数据。

需要注意的是,以上无论临时、缓存或者普通目录,如果不需要的数据,都请删除。不要占用用户的存储空间

  • 各路径对应的OC访问方法
路径 方法
app安装路径 [[NSBundle mainBundle] resourcePath]
app数据沙盒存储根目录 NSHomeDirectory()
Documents NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)
Library NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES)
Caches NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)
tmp NSTemporaryDirectory()

Android

变量 路径
Application.dataPath /data/app/package name-1/base.apk
Application.streamingAssetsPath jar:file:///data/app/package name-1/base.apk!/assets
Application.temporaryCachePath /storage/emulated/0/Android/data/package name/cache
Application.persistentDataPath /storage/emulated/0/Android/data/package name/files

看Android上的路径,跟iOS有点类似,简单说一下。Android的几个目录是apk程序包、内存存储(InternalStorage)和外部存储(ExternalStorage)目录。

  • apk程序包目录: apk的安装路径,/data/app/package name-n/base.apk,dataPath就是返回此目录。
  • 内部存储目录: /data/data/package name-n/,用户自己或其它app都不能访问该目录。打开会发现里面有4个目录(需要root)
    • cache 缓存目录,类似于iOS的Cache目录
    • databases 数据库文件目录
    • files 类似于iOS的Documents目录
    • shared_prefs 类似于iOS的Preferences目录,用于存放常用设置,比如Unity3D的PlayerPrefs就存放于此
  • 外部存储目录: 在内置或外插的sd上,用户或其它app都可以访问,外部存储目录又分私有和公有目录。
    • 公有目录是像DCIM、Music、Movies、Download这样系统创建的公共目录,当然你也可以像微信那样直接在sd卡根目录创建一个文件夹。好处嘛,就是卸载app数据依旧存在。
    • 私有目录在/storage/emulated/n/Android/data/package name/,打开可以看到里面有两个文件夹cache和files。为什么跟内部存储目录重复了?这是为了更大的存储空间,以防内存存储空间较小。推荐把不需要隐私的、较大的数据存在这里,而需要隐私的或较小的数据存在内部存储空间。
  • 各路径对应的Java访问方法
路径 方法
apk包内 AssetManager.open(String filename)
内部存储 context.getFilesDir().getPath() or context.getCacheDir().getPath()
外部存储 context.getExternalFilesDir(null).getPath() or context.getExternalCacheDir().getPath()

在获取android存储路径的时候,如果返回了空字符串,那么可能是漏掉了权限没加

1
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

Windows

变量 路径
Application.dataPath 应用的appname_Data/
Application.streamingAssetsPath 应用的appname_Data/StreamingAssets
Application.temporaryCachePath C:\Users\username\AppData\Local\Temp\company name\product name
Application.persistentDataPath C:\Users\username\AppData\LocalLow\company name\product name

Mac

变量 路径
Application.dataPath 应用的appname_Data/
Application.streamingAssetsPath 应用的appname_Data/StreamingAssets
Application.temporaryCachePath
Application.persistentDataPath

Unity使用

streamingAssetsPath

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
26
27
28
void Awake()
{
string path =
#if UNITY_ANDROID && !UNITY_EDITOR
Application.streamingAssetsPath + "/Josn/modelname.json";
#elif UNITY_IPHONE && !UNITY_EDITOR
"file://" + Application.streamingAssetsPath + "/Josn/modelname.json";
#elif UNITY_STANDLONE_WIN||UNITY_EDITOR
"file://" + Application.streamingAssetsPath + "/Josn/modelname.json";
#else
string.Empty;
#endif
StartCoroutine(ReadData(path));
}

IEnumerator ReadData(string path)
{
WWW www = new WWW(path);
yield return www;
while (www.isDone == false)
{
yield return new WaitForEndOfFrame();
}
yield return new WaitForSeconds(0.5f);
string data = www.text;
yield return new WaitForEndOfFrame();

}
  • 注意
  • 在移动平台下,Application.streamingAssetsPath是只读的,不能写入数据。Application.persistentDataPath 可以读取和写入数据。
  • 在PC下,可以用File类API(如File.ReadAllText)读写StreamingAssets文件夹中的文件;在IOS和Android平台下,不能用File类API读取。
  • 所有平台上都可以用www方式异步读取StreamingAssets文件夹,PC和IOS平台下,读取路径必须加上”file://“,而安卓不需要。
  • 在IOS和Android下,还能用AssetBundle.LoadFromFile来同步读取数据。
1
2
3
4
5
6
7
8
9
string path =
#if UNITY_ANDROID
Application.dataPath + "!assets"+ "/";
#else
Application.streamingAssetsPath + "/";
#endif

AssetBundle assetbundle = AssetBundle.LoadFromFile(path +"sprite.unity3d");
Sprite sprite = assetbundle.LoadAsset<Sprite>("test");