UNITY_资源路径与加载外部文件

https://www.tuicool.com/articles/qMNnmm6
https://blog.csdn.net/appppppen/article/details/51396256
https://unity3d.com/cn/learn/tutorials/topics/best-practices/resources-folder
https://blog.csdn.net/qq_18995513/article/details/51958906

背景:

有许多静态数据是放在客户端中的,比如csv/xml文件,是需要动态读取文件的

实例: 动态读取一个xml文件,并生成一个类

<?xml version="1.0" encoding="UTF-8"?>
<test>
<name>chenjd</name>
<blog>http://www.cnblogs.com/murongxiaopifu/</blog>
<organization>Fanyoy</organization>
<age>25</age>
</test>

将此xml文件随意放在某路径下:Assets/aa/bb/Test.xml

使用代码读取文件内容

void Start() {
XElement result = LoadXML("Assets/aa/bb/Test.xml");
} void LoadXML(string path) {
XElement xml = XElement.Load(path);
return xml;
}

读取成功。

问题1. 路径和地址。在移动端是找不到文件的。
问题2. 使用的是PC上传统的一套读取资源的做法,而没有使用unity3d提供的方法。
  可能导致找得到文件但是没能正确地读取文件内容

移动平台的资源路径:

Application.dataPath: 程序的数据文件所在文件夹。在Editor中就是Assets
  安卓: /data/app/xxx.xxx.xxx.apk
  iOS:  Application/xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/xxx.app/Data

Application.streamingAssetsPath: 流数据的缓存目录,为相对路径,适合设置一些外部数据文件
  安卓: jar:file:///data/app/xxx.xxx.xxx.apk/!/assets
  iOS:  Application/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/xxx.app/Data/Raw

Application.persistentDataPath: 持久化数据存储目录的路径,可用于存储一些持久化的数据文件
  安卓: /data/data/xxx.xxx.xxx/files
  iOS:  Application/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/Documents

Application.temporaryCachePath: 临时数据的缓存目录
  安卓: /data/data/xxx.xxx.xxx/cache
  iOS:  Application/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/Library/Caches

dataPath和streamingAssetsPath一般是相对程序的安装目录位置
persistentDataPath和temporaryCachePath一般是与系统有关的固定位置

那么,打包之后的资源的路径如何与这些地址对应上呢?

Unity中的资源处理种类:

Resources:

如果有文件夹名为Resources,则里面的内容会无条件地在打包时打包集成到.asset文件中
可以放置一些Prefab,因为Prefab在打包时会自动过滤掉不需要的资源,有利于减小资源包
1. 只读。不能动态修改,会动态更新的资源不要放在这里
2. 主线程加载
3. 使用Resources.Load()加载资源

StreamingAssets:

与Resources类似
区别为:Resources文件夹中的内容在打包时会被压缩和加密,而StreamingAssets中的内容则原封不动地打包
一般用来存放一些二进制文件
1. 只读,不能动态修改
2. 主要存放二进制文件
3. 只能通过WWW类读取

AssetBundle:

将prefab或二进制文件封装成AssetBundle文件(也是二进制文件)
缺点: 在移动端无法更新脚本
总结:
1. 该二进制文件(AssetBundle文件) 是Unity3D定义的一种二进制类型
2. 最好将Prefab封装成AssetBundle,但是在移动端无法更新脚本
3. 使用WWW类读取

PersistentDataPath:

这是一个路径(可读写)
在iOS上就是应用程序的沙盒;
在安卓上可以是程序的沙盒或sdCard -- 在安卓打包时,ProjectSetting的选项WriteAccess可设置路径是沙盒还是sdcard
总结:
1. 内容在运行时可读写,提前将数据存入这个路径是不可行的
2. 无内容类型的限制
3. 写下的文件可以在电脑上查看,同样也可以在电脑中清除

移动平台读取外部文件的方法:

使用Unity3D规定的操作方式来读取外部资源:Resources/ StreamingAssets/ AssetBundle

Resources: 

新建Resources目录,在目录中创建文件Test.xml(之前在背景中提到的那个文件)
通过Resources的方法来读取Test.xml中的内容。

public class Test: MonoBehaviour {
private string _result;
void Start(){ LoadXML("Test"); } private void LoadXML(string path){
_result = Resources.Load(path).ToString();
XmlDocument doc = new XmlDocument();
doc.LoadXml(_result);
}
}

StreamingAssets:

新建StreamingAssets文件夹并存放Test.xml文件
(StreamingAssets文件夹中的文件不会被压缩或加密,所以一般是要放二进制文件的,这里放xml只是做一个演示,实际操作中切记不要直接把数据文件放到该目录中)

public class Test : MonoBehaviour {
private string _result;
void Start(){ StartCoroutine(LoadXML()); } IEnumerator LoadXML(){
string path = Application.streamingAssetsPath;
WWW www = new WWW(path);
yield return www;
_result = www.text;
}
}

AssetBundle:

比较麻烦,需要先把Test.xml打包成AssetBundle文件
创建好AssetBundle文件并命名为TestXML后,因为ab文件是二进制文件,因此放入StreamingAssets文件夹。

public class Test: MonoBehaviour {
private string _result;
void Start(){ LoadXML(); } void LoadXML(){
AssetBundle assetBundleCsv = new AssetBundle();
// 读取放入StreamingAssets文件夹中的ab文件
string str = Application.streamingAssetsPath + "/TestXML.bundle";
WWW www = new WWW(str);
www = WWW.LoadFromCacheOrDownload(str, );
assetBundleCsv = www.assetBundle;
string path = "Test";
TextAsset test = assetBundleCsv.Load(path, typeof(TextAsset)) as TextAsset;
_result = test.ToString();
}
}

PersistentDataPath:

只有在运行时才能读写,例如通过网络下载资源存放在PersistantDataPath中

与StreamingAssets的读取很类似,但要注意通过www类加载PersistentDataPath必须使用file://协议实现加载

public class Test: MonoBehaviour{
private string _result;
void Start(){ StartCoroutine(LoadXML()); } private void LoadXML(){
string path = "file://" + Application.persistentDataPath + "/test.xml";
WWW www = new WWW(path);
yield return www;
_result = www.text;
}
}

深入Resources.Load()

Recommendation: DO NOT USE IT.

Reasons:

1. Use of the Resources folder makes fine-grained memory management more difficult;

2. Improper use of Resources folders will increase applicaiton startup time and the length of builds
  The increase of the number of Resources folders makes the management of the "Resources Assets" more difficult;

3. The Resources system degrades a project's ability to deliver custom content to specific platforms and eliminates the possibility of incremental content upgrades
  AssetBundle Variants are Unity's primary tool for adjusting content on a per-device basis

Proper uses:

Two specific use cases where Resources system can be helpful

1. The ease of the Resources folder makes it an excellent system to rapidly prototype.
  But when a project moves into full production, the use of Resources system should be eliminated.

2. When the content is:
  Generally required throughout a project's lifetime
  Not memory-intensive
  Not prone to patching, or does not vary across platforms/ devices
  Used for minimal bootstrapping

  比如: 持有预制体的MonoBehaviour单例、包含第三方配置数据的ScriptableObject容器等

Resources的卸载:

Resources资源类型的加载方式只有一种,但卸载有多种。

1. Resources.UnloadAsset(Object assetToUnload)
  从内存中卸载(非GameObject类型的资源???),会将内存中已加载的资源卸载掉
2. Destroy(obj) 
  仅用于卸载(GameObject类型???)的资源的克隆体
3. DestroyImmediately(obj)
  卸载GameObject类型的资源,会将内存中已加载资源及其克隆体卸载;
  但该方法只能用在非编辑模式下,否则会报错,提示改为DestroyImmediately(obj, true),
  然而编辑模式下使用该函数会连文件夹里的原始Asset一并删除。

官方推荐的卸载方法为:
  public static AsyncOperation UnloadUnusedAssets()
  异步检索资源如果没有被使用才会卸载。
  被全局变量引用的资源会导致一直无法释放。

UNITY_资源路径与加载外部文件的更多相关文章

  1. 背水一战 Windows 10 (11) - 资源: CustomResource, ResourceDictionary, 加载外部的 ResourceDictionary 文件

    [源码下载] 背水一战 Windows 10 (11) - 资源: CustomResource, ResourceDictionary, 加载外部的 ResourceDictionary 文件 作者 ...

  2. django如何加载外部文件

    django如何加载外部文件(环境:pycharm python2.7 django1.11) 有一份新的文件夹名为:py_aiplat_demo,内含有多个文件夹(SDK,demo,data). 1 ...

  3. 资源: CustomResource, ResourceDictionary, 加载外部的 ResourceDictionary 文件

    CustomResource ResourceDictionary 加载外部的 ResourceDictionary 文件 示例1.演示“CustomResource”相关知识点Resource/Cu ...

  4. java加载外部文件数据到代码中:外部数据文件放到jar包中,调用方法getResourceAsStream

    任务要将数据文件geo.txt加载进行.因为是别人写的总体项目,不能乱动位置.只能将geo.txt打包到jar中某目录.比如,放到.class文件下怎么加载:http://riddickbryant. ...

  5. jQuery加载外部文件的方式get、post、ajax、load的区别及异步加载的实现

    一.$.post(url, [data], [callback], [type])  url (String) : 发送请求的URL地址. data (Map) : (可选) 要发送给服务器的数据,以 ...

  6. FusionCharts简单教程(六)------加载外部Logo

    一.加载外部文件Logo       在使用FusionCharts时,我们可能需要在加载图像的时候需要在图表中显示标识.图片等等.这里我们可以使用logoURL属性来实现.如: <chart ...

  7. Java_Java中动态加载jar文件和class文件

    转自:http://blog.csdn.net/mousebaby808/article/details/31788325 概述 诸如tomcat这样的服务器,在启动的时候会加载应用程序中lib目录下 ...

  8. [转载] Java中动态加载jar文件和class文件

    转载自http://blog.csdn.net/mousebaby808/article/details/31788325 概述 诸如tomcat这样的服务器,在启动的时候会加载应用程序中lib目录下 ...

  9. spark-submit --files 动态加载外部资源文件

    在做spark时,有些时候需要加载资源文件,需要在driver或者worker端访问.在client模式下可以使用IO流直接读取,但是在cluster模式下却不能直接读取,需要如下代码: val is ...

随机推荐

  1. jar的解压与打包

    当我们在公司上班时候,时长需要将本地开发的作业打包上传到集群运行,由于项目过多依赖会导致jar比较庞大,因此每一次上传都比较浪费时间,为了节省时间可以使用两种办法: 1:将所有依赖一次性上传到集群上, ...

  2. vue中兄弟之间组件通信

    我们知道Vue中组件之间的通信有很多方式,父子之间通信比较简单,当我们使用vuex时候,兄弟组件之间的通信也很好得到解决 当我们项目较小时候,不使用vuex时候Vue中兄弟组件之间的通信是怎样进行的呢 ...

  3. kubernetes 网络模型

    在Kubernetes模型中,每个Docker主机的docker0网桥都是可以路由的. 那就是说,当一个Pod部署后,集群其他主机能够不在物理主机上做端口映射就可以直接访问Pod. 有了这种说法,从网 ...

  4. CoreText 关键性常用函数说明

    CoreText是专门进行文字绘制的函数集合 CoreText 将单个字符分为 · baseline(基线),一条假想的线,一行上的字形都以此线作为上下位置的参考,在这条线的左侧存在一个点叫做基线的原 ...

  5. Linux学习笔记(第六章)

    第六章-档案权限与目录配置#chgrp:改变档案的所属群组#chown:改变档案的拥有者#chmod:改变档案的权限及属性 chown用法 chmod用法: r:4 w:2 x:1对于文档: 对于目录 ...

  6. vue实现两重列表集合,点击显示,点击隐藏的折叠效果,(默认显示集合最新一条数据,点击展开,显示集合所有数据)

    效果图: 默认显示最新一条数据: 点击显示所有数据: 代码: 说明:这里主要是 这块用来控制显示或者隐藏 根据当前点击的  这个方法里传递的index 对应  isShow 数组里的index  ,对 ...

  7. PHP中查询一个日期是周几

    PHP查询一个日期是周几 1.date('l'),获取的是英文的星期几.Sunday 到 Saturday date('l', strtotime('2019-4-6')); // Saturday ...

  8. C中gets()函数与scanf()函数说明

    scanf( )函数和gets( )函数都可用于输入字符串,但在功能上有区别.若想从键盘上输入字符串"hi hello",则应该使用 gets 函数. gets可以接收空格:而sc ...

  9. C 修真之旅

    前言 - 那久远的故事 工作好多年, 有时脑海里总回想儿时看的梦. 那时还刚上初中, 班上个子小的同学, 闲暇娱乐可能就是看 <飘渺之旅> 之类的小说. 前几年尝试满足自己少年时的记忆. ...

  10. inux下进程的最大线程数、进程最大数、进程打开的文件数

    inux下进程的最大线程数.进程最大数.进程打开的文件数 2008-12-07 23:48 =========================    如下转载自这里. linux 系统中单个进程的最大 ...