Unity在iOS/Android/Windows平台应用存储路径_unity 安卓路径-程序员宅基地

技术标签: unity  Unity3D  游戏引擎  android  

游戏在Android手机上启动时无法正常进入,经查发现Application.temporaryCachePath和Application.persistentDataPath返回空字符串,这是一个在不同平台的路径问题。

常用的是以下四个路径:

Application.dataPath
Application.streamingAssetsPath
Application.persistentDataPath
Application.temporaryCachePath

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


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" />

另一个问题就是,assetbundle资源更新到 Application.persistentDataPath这个路径,然后加载资源就从这个路径加载。

    首先这个目录呢是本地持久化的目录,不是安卓apk包里面的东西。

    读取assetbundle的正确路径是:"file://"+ Application.persistentDataPath+"/"+fileName

前面测试的时候还傻傻地使用这个路径:"jar:file://" +Application.persistentDataPath + "!/assets"+...

这个路径是读取apk包里面的资源。不是读取本地持久化目录的里面的东西
 


PlayerPrefs路径(补充)

Android: /data/data/pkg-name/shared_prefs/pkg-name.v2.playerprefs.xml
iOS:/Library/Preferences/[bundle identifier].plist

Mac:~/Library/Preferences/com.CompanyName.ProductName.plist

Windows:HKEY_CURRENT_USER/Software/CompanyName/ProductName

(win+R打开“运行”输入regedit打开注册表),Windows 10使用应用程序的PlayerPrefs名称。例如,Unity添加一个DeckBase字符串并将其转换为DeckBase_h3232628825。该应用程序将忽略扩展名。其中company name和product name名是在Project Setting中设置

Unity将PlayerPrefs存储在本地注册表中,无需加密。不要使用PlayerPrefs数据存储敏感数据。
 

Unity3D研究院之手游开发中所有特殊的文件夹(assetbundle与Application.persistentDataPath)_每天进步一点点的技术博客_51CTO博客

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_42672770/article/details/124664611

智能推荐

ASAN 问题总结-程序员宅基地

文章浏览阅读940次,点赞3次,收藏11次。MemShadowshadow memory也是内存中的一块区域,但与main memory又不同,shadow memory中有元数据的思想,其中的数据存放的是 main memory 的状态信息。因此,可以将 shadow memory 看做是 main memory 的元数据,而 main memory 中存储的才是程序真正的数据。_asan

算法导论 CLRS 19.2-8 解答-程序员宅基地

文章浏览阅读180次。假设二项堆H的第一个空缺的二项树为Bk, 则插入一个关键字x之后,必然是有B0, B1, .., Bk-1加上x组成Bk过程如下1. 遍历H的根表,同时比较x和各个二项树的根关键字,记录最小的关键字,直到空缺的二项树Bk2.如果最小关键字为某个二项树Bj的根,则将Bj的根替换为x,然后将x下沉;3. 以最小的关键字为根,B0, B1,...,Bk-1为孩子组成..._clrs 19.2-1

数学通道的应用(十五)-电阻的测量_示波器测高电阻通道乘几-程序员宅基地

文章浏览阅读1.2k次。在我们推出4425A示波器PicoBNC+电阻测试线的介绍视频之后,有人提出了可不可以用4425示波器测量电阻这个问题。这绝对是有可能的。我们必须了解正在测量的电路,捕获电压和电流信号(在有负载的情况下),并使用欧姆定律来计算电阻。图1是一个典型示例,我们在Maths is Cool第一篇文章中介绍过了起动机的电压和电流。 图1 电..._示波器测高电阻通道乘几

c语言指针取10个数中最大值和最小值,C语言提问:用指针法,有10个数围成一个圈,求出相邻三个数之和的最小值。,从0,1,2……9等1...-程序员宅基地

文章浏览阅读1.1k次。#includevoid _max_cycle_sum(int *a,int len){int *p,*q,sum,i=0,j,total=0;p=a;q=a;for(i=0;i<=len-1;i++){//用total作为待比较的数对其初始化,因为连续的三位和比其数组总和小total+=*q++;}i=0;while(i<=len-1){//不难分析出的到的每三个数为一组答案,共有l..._用while写指针查找最大值和最小值

机房服务器显示器切换主机,某机关单位机房运用迈拓维矩IP-KVM切换器解决方案...-程序员宅基地

文章浏览阅读375次。使用背景:某机关单位在机房有16台独立工控主机,要求既可以在机房本地通过一套IP KVM切换器能实现对这16台设备上架管理,另外,管理员可以在外地通过因特网能随时登陆 IP KVM切换器上 ,实现对IP KVM 所连接主机的访问,管控操作。技术要求:1、机柜内的16台设备作为一个独立单元,要求通过一套设备即可实现对本机柜内的主机进行管控。2、管理员能够实现通过IP远程进行服务器的休眠唤醒。3、所有..._底图功能 迈拓维矩

Android逆向之反编译APK_apk反编译-程序员宅基地

文章浏览阅读895次。1、反编译资源,主要通过 apktool2、反编译代码,主要通过 dex2jar + jd-gui3、基于一个 app 打造一个新的 app,主要通过 apktool 反编译后,修改 activity_main.xml 文件,然后进行重新打包,签名,对齐,最后安装展示了预期的效果。_apk反编译

随便推点

【券商报告】基础化工行业月报:行业维持景气态势,继续关注制冷剂和化纤——附下载链接_化纤 行研报告-程序员宅基地

文章浏览阅读63次。来源 | 中原证券全球基础化学品需求总量约为 6.5 亿吨/年,其中乙烯、丙烯、甲醇、氯气、苯和对二甲苯六大价值链约占其中的 80%。2020 年, 这 6 种化学品需求较前一年下降约 1000 万吨,下降幅度远低于预期。基础化学品需求下降幅度相对较小主要是因为 50%的基础化学品作为塑料被消费。与食品、饮料、卫生和医疗包装等 相关的非耐用品的乙烯需求得到聚乙烯(PE)需求支撑,这一块需求占到全球乙烯需求的 63%。 此外,对于乙烯行业,由于前一段时期盈利持续强劲和新项目投资增加,造成需求与产能之间 的_化纤 行研报告

mysql 单独join_MySQL的各种Join-程序员宅基地

文章浏览阅读564次。写在最前面所有的内容都是通过资料自行整理总结出来的,包括SQL代码也是自己一行一行自己敲出来试过的,因此未授权禁止进行转载由于本人能力有限,自行进行整理的内容未必100%准确,因此若有内容不当之处,还请各位大神指正为了更好理解其中的各种 join,现在建立两张表 tbl_subject 和 tbl_student_score ,表结构如下:tbl_subject 表结构及内容.pngtbl_stu..._mysql 单独使用join

图像处理与计算机视觉基础,经典以及最近发展--转载-程序员宅基地

文章浏览阅读277次。*************************************************************************************************************** 在这里,我特别声明:本文章的源作者是 杨晓冬 (个人邮箱:[email protected])。原文的链接是http://www.iask.s..._scale space localization, blur, and contour-based image coding

批量查询ip地址的归属地-程序员宅基地

文章浏览阅读1.3k次。1234567#!/bin/bash#批量查找ip地址所在地whilereadidosring=`curl-s"http://ip138.com/ips138.asp?ip=${i}&action=2"|iconv-fgb2312-tutf-8|grep'1.'|awk-F..._批量查询ip地址归属地

Python--网络编程-程序员宅基地

文章浏览阅读54次。Python--网络编程socket模块套接字起源于 20 世纪 70 年代加利福尼亚大学伯克利分校版本的 Unix,即人们所说的 BSD Unix。 因此,有时人们也把套接字称为“伯克利套接字”或“BSD 套接字”。一开始,套接字被设计用在同 一台主机上多个应用程序之间的通讯。这也被称进程间通讯,或 IPC。套接字有两种(或者称为有两个种族),分别是基于文件型的和基于网络型的。基于...

[敏捷开发实践](1) 认识敏捷开发-程序员宅基地

文章浏览阅读254次。[敏捷开发实践](1) 认识敏捷开发1,提要 软件开发是一个系统工程,包括最初的可行性分析、再到设计、开发、测试、维护等整个生命周期。在这个过程中某些阶段的失误或说是变化,都可能增加整个软件项目的风险。 如何在保证效率的基础上还能安计划、保证质量的完成软件项目?于是产生了软件开发的一些方法,这个方法不是指具体有编码阶段的各种设计模式和技巧,而是在整个软件开发策略层面..._scrum 角色 会议 微软