前几天我们游戏在一个同事的Android手机上启动时无法正常进入,经查发现Application.temporaryCachePath和Application.persistentDataPath返回空字符串。便花时间认真研究了一下Unity3D的路径问题。我们常用的是以下四个路径:

Application.dataPath

Application.streamingAssetsPath

Application.persistentDataPath

Application.temporaryCachePath

根据测试,详细情况如下:


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

iOS和Mac 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存储的原理,最后来说说开头提到的bug,Application.temporaryCachePath/persistentDataPath返回空字符串。这其实因为权限的原因,app没有声明访问外部存储空间的权限,但是Application.temporaryCachePath/ ApplicationpersistentDataPath却想返回外部存储的路径。这是Unity3D的bug,没有权限本应该抛出一个异常或者错误,让开发者知道原因。

经反复测试发现,有【外置SD卡】的设备上,如果声明读/写外部存储设备的权限,会返回外部存储路径,不声明则会返回内部存储路径,这样不会有问题。而在【无外置SD卡】的设备上,不管是否声明读/写外部存储设备的权限,Application.temporaryCachePath/persistentDataPath都返回外部存储路径,但是又没有权限,就可能会导致返回null了,之所以说可能是因为这个bug不是必现,如果出现了设备重启之后就好了,怀疑是linux设备mount问题。但是出了问题,我们不能跟用户说你重启一下手机就好了。

<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


参考:

  1. iOS Data Storage Guidelines
  2. Android API: Storage Options
  3. 彻底理解Android中的内部存储与外部存储

PS. 如果你对各平台文件管理或热更新有兴趣,欢迎一起讨论。

Unity3D各平台Application.xxxPath的路径的更多相关文章

  1. Unity3D移动平台动态读取外部文件全解析

    前言: 一直有个想法,就是把工作中遇到的坑通过自己的深挖,总结成一套相同问题的解决方案供各位同行拍砖探讨.眼瞅着2015年第一个工作日就要来到了,小匹夫也休息的差不多了,寻思着也该写点东西活动活动大脑 ...

  2. (转)Unity3D移动平台动态读取外部文件全解析

    Unity3D移动平台动态读取外部文件全解析 c#语言规范 阅读目录 前言: 假如我想在editor里动态读取文件 移动平台的资源路径问题 移动平台读取外部文件的方法 补充: 回到目录 前言: 一直有 ...

  3. 慕容小匹夫 Unity3D移动平台动态读取外部文件全解析

    Unity3D移动平台动态读取外部文件全解析   c#语言规范 阅读目录 前言: 假如我想在editor里动态读取文件 移动平台的资源路径问题 移动平台读取外部文件的方法 补充: 回到目录 前言: 一 ...

  4. Application中的路径

    前提条件 项目工程目录:E:/Work/cosmosbox/cb-client/ 我电脑当前的用户名:qingqing PersistentDataPath Application.persisten ...

  5. Unity3d各平台资源路径文件夹

    之前一直是PC项目,公司终于考虑移动平台了,但是试验了几把,感觉移动平台资源管理路径还是有很多隐藏的注意事项. 比如在PC上可以做到随便读写,但是在移动平台就涉及到权限问题. 看到小伙伴的总结,还是要 ...

  6. Unity3D 多平台 预编译 宏定义

    平台定义 UNITY_EDITOR 编辑器调用. UNITY_STANDALONE_OSX 专门为Mac OS(包括Universal,PPC和Intelarchitectures)平台的定义. UN ...

  7. Unity3D 多平台_预编译相关宏定义

    http://www.cnblogs.com/zhaoqingqing/p/3510332.html API地址:http://docs.unity3d.com/Documentation/Manua ...

  8. Qt配置信息设置(QSettings在不同平台下的使用路径)

    在Windows操作系统中,大多把配置文件信息写在注册表当中,或写在*.ini文件中,对于这两种操作都有相应的Windows API函数,在以前的文章中都提及过,这里就不多说了~ 在Qt中,提供了一个 ...

  9. Application.CommonAppDataPath的路径

    Application.CommonAppDataPath; win7的路径 C:\ProgramData\CompanyName\ProductName\2.0.5.1 [assembly: Ass ...

随机推荐

  1. 【转载】C++基本功和 Design Pattern系列 ctor & dtor

    最近实在是太忙了,无工夫写呀.只能慢慢来了.呵呵,今天Aear讲的是class.ctor 也就是constructor, 和  class.dtor, destructor. 相信大家都知道const ...

  2. JVMGC机制

    GC 是JVM的垃圾回收器.与C/C++不同,java程序员无需考虑太多内存分配的位置,更不用考虑内存释放的机制,java对象内存的申请和释放都有JVM托管.JVM的内存释放机制就是GC. GC的过程 ...

  3. CSS 权威指南 CSS实战手册 第四版(阅读笔记)

    前言: 对于程序员,学习是无止境的,知识淘换非常快,能够快速稳固掌握一门新技术,是一个程序员应该具备的素质.这里将分析本人一点点不成熟的心得. 了解一门语言,了解它的概念非常重要,但是一些优秀的设计思 ...

  4. ASP.NET Core 如何在运行Docker容器时指定容器外部端口

    前面我写了一系列关于持续集成的文章,最终构建出来的镜像运行之后,应该会发现每次构建运行之后端口都变了,这对于我们来说是十分不方便的,所以我们可以通过修改docker compose的配置文件来完成我们 ...

  5. springboot全局异常处理

    @Slf4j@ControllerAdvicepublic class RestExceptionHandler extends ResponseEntityExceptionHandler { @E ...

  6. [BZOJ 2144]跳跳棋

    Description 跳跳棋是在一条数轴上进行的.棋子只能摆在整点上.每个点不能摆超过一个棋子.我们用跳跳棋来做一个简单的游戏:棋盘上有3颗棋子,分别在a,b,c这三个位置.我们要通过最少的跳动把他 ...

  7. clique

    [题目描述]数轴上有 n 个点,第 i 个点的坐标为 xi,权值为 wi.两个点 i,j 之间存在一条边当且仅当 abs(xi-xj)>=wi+wj.你需要求出这张图的最大团的点数.(团就是两两 ...

  8. Conjugate

    1.1Conjugate问题描述在不存在的 noip day3 里,小 w ⻅到了一堆堆的谜题.比如这题为什么会叫共轭?他并不知道答案.有 n 堆谜题,每堆有 a i 个,小 w 每次从剩下的谜题中选 ...

  9. ●POJ 2007 Scrambled Polygon

    题链: http://poj.org/problem?id=2007 题解: 计算几何,极角排序 按样例来说,应该就是要把凸包上的i点按 第三像限-第四像限-第一像限-第二像限 的顺序输出. 按 叉积 ...

  10. NOIP 2014

    Prob.1 生活大爆炸版 石头剪刀布 模拟.代码: #include<cstdio> #include<cstring> #include<iostream> u ...