【Unity】数据持久化路径Application.persistentDataPath
今天突然想到这个路径Application.persistentDataPath,热更的重要路径,该文件夹可读可写,在移动端唯一一个可读写操作的文件夹。
移动端可以将本地的资源(资源MD5值配置表)等一些文件放到StreamingAssets文件夹下,通过Copy到persistentDataPath下与服务器的版本文件配置表作比对,完成资源的热更。
为什么不在StreamingAsset文件夹下直接操作?因为该文件夹只读,不可写,资源无法更新进去。
为什么不在persistentDataPath文件夹操作,因为该文件夹是apk安装以后,才会形成的一个文件夹,无法提前创建。
本来以为,persistentDataPath文件夹,是每次打开游戏,形成的,里面的数据是只在打开游戏期间临时保存,关闭游戏就会消除,今天做个小测试,原来该文件夹是安装完apk以后形成,里面的数据持久存在。
public Text ShowText;public Button WriteBtn, ReadBtn, QuitBBtn;private void Start(){WriteBtn.onClick.AddListener(WriteEvent);ReadBtn.onClick.AddListener(ReadEvent);QuitBBtn.onClick.AddListener(QuitEvent);}private void WriteEvent(){StreamWriter st = File.CreateText(Application.persistentDataPath + "Test.txt");st.Write("测试一下");st.Close();}private void ReadEvent(){ShowText.text = File.ReadAllText(Application.persistentDataPath + "Test.txt");}private void QuitEvent(){Application.Quit();}

先写入该文件夹一些内容,退出游戏,再次打开,从该文件夹读取,显示出来。

事实证明该文件夹数据一直存在。
Unity3D各平台Application.xxxPath的路径
前几天我们游戏在一个同事的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" />
1
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
PlayerPrefs路径(补充)
Android: /data/data/pkg-name/shared_prefs/pkg-name.v2.playerprefs.xml
iOS:/Library/Preferences/[bundle identifier].plist
Windows:HKEY_CURRENT_USER/Software/CompanyName/ProductName
Mac:~/Library/Preferences/com.CompanyName.ProductName.plist
————————————————
相关文章:

【Unity】数据持久化路径Application.persistentDataPath
今天突然想到这个路径Application.persistentDataPath,热更的重要路径,该文件夹可读可写,在移动端唯一一个可读写操作的文件夹。移动端可以将本地的资源(资源MD5值配置表)等一些文件放到StreamingAssets文件夹下&#…...
华为OD机试 - 插队(Java JS Python)
题目描述 某银行将客户分为了若干个优先级, 1 级最高, 5 级最低,当你需要在银行办理业务时,优先级高的人随时可以插队到优先级低的人的前面。 现在给出一个人员到来和银行办理业务的时间序列,请你在每次银行办理业务时输出客户的编号。 如果同时有多位优先级相同且最高…...
MongoDB数据库从入门到精通系列之八:调整oplog大小
MongoDB数据库从入门到精通系列之八:调整oplog大小 一、oplog的概念二、oplog大小三、调整oplog大小详细步骤一、oplog的概念 操作日志oplog包含了主节点执行的每一次写操作。oplog是存在于主节点local数据库中的一个固定集合。从节点通过查询此集合以获取需要复制的操作。每个…...
PCL 间接平差法拟合二维直线
目录 一、算法原理二、代码实现三、结果展示四、相关链接一、算法原理 通过传统最小二乘法对点云数据进行二维直线拟合时,可将误差只归因于一个方向上,本文假设误差只存在于 y y y轴方向上,设点云拟合的二维直线方程为: y =...

进程调度的基本过程
这里写目录标题什么是进程进程管理结构体或类的主要属性pid内存指针文件描述符表辅助进程调度的属性并发并行并发什么是进程 进程是操作系统对一个正在运行的程序的一种抽象,也就是说,一个运行起来的程序就是一个进程。 进程又是操作系统进行资源分配的…...

python自动化办公(二)
上接python自动化办公(一) 文章目录文件和目录操作使用shutil库文件查找globfnmatchhashlib文件和目录操作 使用shutil库 shutil库也是Python标准库,它可以处理文件、文件夹、压缩包,能实现文件复制、移动、压缩、解压缩等功能。…...

Qt Quick - GridLayout 网格布局
GridLayout 理论总结一、概述二、依赖属性三、例子1. 不含跨行的2. 带跨行列的3. 从右到左一、概述 GridLayout 是最常用的布局器,也叫网格布局器,如果网格布局被调整大小,布局中的所有 Item 将被重新排列。它类似于基于widget的QGridLayout…...

安卓手机也可以使用新必应NewBing
没有魔法安卓手机也可以使用新必应NewBing 目前知道的是安卓手机 安卓手机先安装一个猴狐浏览器 打开手机自带浏览器,搜索关键词:猴狐浏览器,找到官网 也可以直接复制这个网址 狐猴浏览器 lemurbrowser CoolAPK 我的手机是荣耀安卓手机…...

支付系统设计:消息重试组件封装
文章目录前言一、重试场景分析一、如何实现重试1. 扫表2. 基于中间件自身特性3. 基于框架4. 根据公司业务特性自己实现的重试二、重试组件封装1. 需求分析2. 模块设计2.1 持久化模块1. 表定义2. 持久化接口定义3. 持久化配置类2.2 重试模块1.启动2.重试3. 业务端使用1. 引入依赖…...

Visual Studio 2022 c#中很实用的VS默认快捷键和原生功能
常常使用VS感觉还是有必要掌握其默认的快捷键,我这个人比较懒,不喜欢动不动就去设置快捷键,系统有就用,记住了就可以到处用,问题是像我们这种有很多个工作场所的人不可能每台电脑都去配置一下快键键。实际上我使用3dma…...

Python的30个编程技巧
1. 原地交换两个数字 Python 提供了一个直观的在一行代码中赋值与交换(变量值)的方法,请参见下面的示例: x,y 10,20 print(x,y) x,y y,x print(x,y) #1 (10, 20) #2 (20, 10) 赋值的右侧形成了一个新的元组,左侧立即解…...

MySQL:JDBC
什么是JDBC? JDBC( Java DataBase Connectivity ) 称为 Java数据库连接 ,它是一种用于数据库访问的应用程序 API ,由一组用Java语言编写的类和接口组成,有了JDBC就可以 用统一的语法对多种关系数据库进行访问,而不用担…...

C++【list容器模拟实现函数解析】
list容器&&模拟实现函数解析 文章目录list容器&&模拟实现函数解析一、list容器使用介绍二、list容器模拟实现及函数解析2.1 list结构体创建2.2 迭代器封装2.21 构造函数:2.22 前置和后置及- -2.23 解引用2.24 判断相等2.25 箭头重载2.26 第二个和第…...
(Java)试题 算法提高 约数个数
一、题目 (1)资源限制 内存限制:512.0MB C/C时间限制:1.0s Java时间限制:3.0s Python时间限制:5.0s (2)输入 输入一个正整数N (3)输出 N有几个约数 &a…...

魔法反射--java反射初入门(基础篇)
👳我亲爱的各位大佬们好😘😘😘 ♨️本篇文章记录的为 java反射初入门 相关内容,适合在学Java的小白,帮助新手快速上手,也适合复习中,面试中的大佬🙉🙉🙉。 ♨️如果文章有…...
概率统计_协方差的传播 Covariance Propagation
1. 方差的传播 误差的传播是指分析在形如的关系中,参量误差(x)对变量误差(y)的影响有多大。误差的传播与函数的微分紧密相关,本质是在利用当Δ x 不大时,。 方差计算公式: X为变量,为总体均值,N为总体例数。求变量X与均值的差的平方再求平均值,即得到方差。方差…...

大学生考研的意义?
当我拿起笔头,准备写这个话题时,心里是非常难受的,因为看到太多的学生在最好的年华,在自由的大学本应该开拓知识,提升认知,动手实践,不断尝试和试错,不断历练自己跳出学生思维圈&…...

【C++笔试强训】第三十一天
🎇C笔试强训 博客主页:一起去看日落吗分享博主的C刷题日常,大家一起学习博主的能力有限,出现错误希望大家不吝赐教分享给大家一句我很喜欢的话:夜色难免微凉,前方必有曙光 🌞。 选择题 &#x…...

toString()、equals()是什么,为啥需要重写,多种方法来重写
https://m.runoob.com/java/java-object-class.html toString() 1.为什么会有toString 子类继承父类就可以使用父类所有非私有的属性的方法。 在Java中所有类都直接或者间接继承Object类,可以说只要是Object类里面定义的非私有的属性和方法,任何类都可…...

家装材料清单中会有哪些装饰材料?
在家居装修中,业主可以根据装修公司出具的材料清单去一一采购,这样不至于有遗漏,就算采用全包的方式,通过材料清单也可以大致了解当时房子装修所用的材料,补充自己的装修知识。下面跟随小编一起了解下房子装修材料中所…...

iOS 26 携众系统重磅更新,但“苹果智能”仍与国行无缘
美国西海岸的夏天,再次被苹果点燃。一年一度的全球开发者大会 WWDC25 如期而至,这不仅是开发者的盛宴,更是全球数亿苹果用户翘首以盼的科技春晚。今年,苹果依旧为我们带来了全家桶式的系统更新,包括 iOS 26、iPadOS 26…...

智慧医疗能源事业线深度画像分析(上)
引言 医疗行业作为现代社会的关键基础设施,其能源消耗与环境影响正日益受到关注。随着全球"双碳"目标的推进和可持续发展理念的深入,智慧医疗能源事业线应运而生,致力于通过创新技术与管理方案,重构医疗领域的能源使用模式。这一事业线融合了能源管理、可持续发…...

LeetCode - 394. 字符串解码
题目 394. 字符串解码 - 力扣(LeetCode) 思路 使用两个栈:一个存储重复次数,一个存储字符串 遍历输入字符串: 数字处理:遇到数字时,累积计算重复次数左括号处理:保存当前状态&a…...
sqlserver 根据指定字符 解析拼接字符串
DECLARE LotNo NVARCHAR(50)A,B,C DECLARE xml XML ( SELECT <x> REPLACE(LotNo, ,, </x><x>) </x> ) DECLARE ErrorCode NVARCHAR(50) -- 提取 XML 中的值 SELECT value x.value(., VARCHAR(MAX))…...
TRS收益互换:跨境资本流动的金融创新工具与系统化解决方案
一、TRS收益互换的本质与业务逻辑 (一)概念解析 TRS(Total Return Swap)收益互换是一种金融衍生工具,指交易双方约定在未来一定期限内,基于特定资产或指数的表现进行现金流交换的协议。其核心特征包括&am…...
Unit 1 深度强化学习简介
Deep RL Course ——Unit 1 Introduction 从理论和实践层面深入学习深度强化学习。学会使用知名的深度强化学习库,例如 Stable Baselines3、RL Baselines3 Zoo、Sample Factory 和 CleanRL。在独特的环境中训练智能体,比如 SnowballFight、Huggy the Do…...
爬虫基础学习day2
# 爬虫设计领域 工商:企查查、天眼查短视频:抖音、快手、西瓜 ---> 飞瓜电商:京东、淘宝、聚美优品、亚马逊 ---> 分析店铺经营决策标题、排名航空:抓取所有航空公司价格 ---> 去哪儿自媒体:采集自媒体数据进…...

如何在最短时间内提升打ctf(web)的水平?
刚刚刷完2遍 bugku 的 web 题,前来答题。 每个人对刷题理解是不同,有的人是看了writeup就等于刷了,有的人是收藏了writeup就等于刷了,有的人是跟着writeup做了一遍就等于刷了,还有的人是独立思考做了一遍就等于刷了。…...
Device Mapper 机制
Device Mapper 机制详解 Device Mapper(简称 DM)是 Linux 内核中的一套通用块设备映射框架,为 LVM、加密磁盘、RAID 等提供底层支持。本文将详细介绍 Device Mapper 的原理、实现、内核配置、常用工具、操作测试流程,并配以详细的…...

云原生玩法三问:构建自定义开发环境
云原生玩法三问:构建自定义开发环境 引言 临时运维一个古董项目,无文档,无环境,无交接人,俗称三无。 运行设备的环境老,本地环境版本高,ssh不过去。正好最近对 腾讯出品的云原生 cnb 感兴趣&…...