Babybus-u3d技術(shù)交流-移動(dòng)平臺(tái)動(dòng)態(tài)讀取外部文件全解析
[ 移動(dòng)平臺(tái)動(dòng)態(tài)讀取外部文件全解析
前言:
一直有個(gè)想法氓拼,就是把工作中遇到的坑通過(guò)自己的深挖總結(jié)成一套相同[問(wèn)題
的解決方案供各位同行拍磚探討此迅。眼瞅著2015年第一個(gè)工作日就要來(lái)到了镜撩,小匹夫也休息的差不多了,尋思著也該寫(xiě)點(diǎn)東西活動(dòng)活動(dòng)大腦和手指了拨匆。那么今天開(kāi)始姆涩,小匹夫會(huì)記錄一些平時(shí)工作中遇到的坑,以及小匹夫的應(yīng)對(duì)方法惭每,歡迎各位拍磚討論。那么今天主要討論一下[unity
3D在移動(dòng)端如何動(dòng)態(tài)的讀取外部文件,比如csv(txt),xml一類(lèi)的文件台腥。主要涉及的問(wèn)題宏赘,就是PC端上本來(lái)測(cè)試的好好的東西,到了移動(dòng)端就不能用了黎侈,所以要討論一下PC端和移動(dòng)端的區(qū)別察署,那么下一個(gè)問(wèn)題自然而然的就是移動(dòng)端的資源路徑(要討論一下Resources、StreamingAssets峻汉、AssetBundle贴汪、PersistentDataPath),最后一步就是找到了資源如何讀刃莘汀(這里也會(huì)具體到對(duì)應(yīng)的幾種情況扳埂,即Resources、StreamingAssets瘤礁、AssetBundle)阳懂,主要的思路就是這樣啦。對(duì)嘞柜思,前言部分還是要祝各位看官新的一年身體健康岩调,升職加薪。假如我想在editor里動(dòng)態(tài)讀取文件
實(shí)際的游戲開(kāi)發(fā)中赡盘,其實(shí)有相當(dāng)一部分靜態(tài)數(shù)據(jù)是可以放在客戶(hù)端的号枕,所以勢(shì)必會(huì)產(chǎn)生要?jiǎng)討B(tài)讀取這些文件的需求,比如csv(其實(shí)就是文本文件)陨享,xml等等葱淳。我相信大家不管是用win還是用mac來(lái)做[unity3d
的開(kāi)發(fā),都一定要先在editor中去實(shí)現(xiàn)基本的功能霉咨,在具體到各個(gè)移動(dòng)平臺(tái)上去調(diào)試蛙紫。所以作為要讀取外部文件的第一步,顯然我們要先在editor也就是pc上實(shí)現(xiàn)這個(gè)功能途戒。下面給各位舉一個(gè)讀取xml的例子坑傅,也是我在以前的一篇文章《自己動(dòng)手之使用反射和泛型,動(dòng)態(tài)讀取XML創(chuàng)建類(lèi)實(shí)例并賦值》中使用過(guò)的喷斋,動(dòng)態(tài)讀取一個(gè)xml文件并動(dòng)態(tài)生成一個(gè)類(lèi)唁毒。下面是我們用來(lái)做例子的xml文件,Test.xml:
[XML] *純文本查看
*復(fù)制代碼
<?xmlversion="1.0"encoding="UTF-8"?>
<test>
<name>chenjd</name>
<blog>http://www.cnblogs.com/murongxiaopifu/</blog>
<organization>Fanyoy</organization> <age>25</age>
</test>
我們就可以很任性的把這個(gè)文件隨便丟在一個(gè)地方星爪,只要你能指定對(duì)它的地址浆西。例如我還把它放在那篇文章中的地址Assets/xml-to-egg/xml-to-egg-test/
[C#] *純文本查看
*復(fù)制代碼
//讀取xml測(cè)試
using UnityEngine;
using System.Collections;
using EggToolkit;
using System.Xml.Linq;
public class Test : MonoBehaviour {
// Use this for initialization
void Start () {
XElement result = LoadXML("Assets/xml-to-egg/xml-to-egg-test/Test.xml");
//任性的地址
Debug.Log(result.ToString());
}
// Update is called once per frame
void Update () {
}
private XElement LoadXML( string path)
{
XElement xml = XElement.Load(path);
return xml;
}
}
結(jié)果如下:結(jié)果是讀取成功了。但是你以為到這一步就成功了顽腾,那就錯(cuò)了近零。因?yàn)檫@樣的代碼到移動(dòng)端是行不通的诺核,至少2處可以被罵sb:
醉人的地址,地址參數(shù)那樣寫(xiě)就不用考慮跨平臺(tái)了久信。所以這個(gè)sb點(diǎn)引出的問(wèn)題就是在移動(dòng)端unity3d找不到目標(biāo)文件
窖杀。
使用的還是pc上傳統(tǒng)的一套讀取資源的做法,沒(méi)有使用unity3d提供的方法裙士,所以可能導(dǎo)致的問(wèn)題是找得到文件但是沒(méi)有正確的讀取文件內(nèi)容
入客。
以上用紅色標(biāo)出的問(wèn)題,便是小匹夫想到的可能出現(xiàn)的問(wèn)題腿椎,也是下文要討論的內(nèi)容桌硫。那么我們首先來(lái)看看資源路徑在各個(gè)平臺(tái)上的不同之處吧。移動(dòng)平臺(tái)的資源路徑問(wèn)題
想要讀取一個(gè)文件啃炸,自然首先要找到這個(gè)文件铆隘,下面小匹夫首先會(huì)總結(jié)一下unity3d中存在的各個(gè)地址,之后再總結(jié)一下各個(gè)地址在各個(gè)移動(dòng)平臺(tái)中的對(duì)應(yīng)位置肮帐。Unity3D中的資源路徑
Application.dataPath
此屬性用于返回程序的數(shù)據(jù)文件所在文件夾的路徑咖驮。例如在Editor中就是Assets了。
Application.streamingAssetsPath
此屬性用于返回流數(shù)據(jù)的緩存目錄训枢,返回路徑為相對(duì)路徑托修,適合設(shè)置一些外部數(shù)據(jù)文件的路徑。
Application.persistentDataPath
此屬性用于返回一個(gè)持久化數(shù)據(jù)存儲(chǔ)目錄的路徑恒界,可以在此路徑下存儲(chǔ)一些持久化的數(shù)據(jù)文件睦刃。
Application.temporaryCachePath
此屬性用于返回一個(gè)臨時(shí)數(shù)據(jù)的緩存目錄。
[android
平臺(tái)
Application.dataPath
/data/app/xxx.xxx.xxx.apk
Application.streamingAssetsPath
jar:file:///data/app/xxx.xxx.xxx.apk/!/assets
Application.persistentDataPath
/data/data/xxx.xxx.xxx/files
Application.temporaryCachePath
/data/data/xxx.xxx.xxx/cache
IOS平臺(tái)
Application.dataPath
Application/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/xxx.app/Data
Application.streamingAssetsPath
Application/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/xxx.app/Data/Raw
Application.persistentDataPath
Application/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/Documents
Application.temporaryCachePath
Application/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/Library/Caches
從上面的3張表格十酣,我們可以看到 dataPath和streamingAssetsPath的路徑位置一般是相對(duì)程序的安裝目錄位置涩拙,而persistentDataPath和temporaryCachePath的路徑位置一般是相對(duì)所在系統(tǒng)的固定位置。那么現(xiàn)在明確了unity3d中各個(gè)地址在不同平臺(tái)上的含義耸采,下一個(gè)問(wèn)題就來(lái)了兴泥,也就是我打包之后的資源要怎么和這些地址對(duì)應(yīng)上呢?要知道在pc的editor里默認(rèn)的資源文件存放的路徑就是Assets啊虾宇,為何又會(huì)派生出那么多路徑呢搓彻?那么就帶著這個(gè)疑問(wèn),和小匹夫一起進(jìn)行下文的內(nèi)容吧嘱朽。簡(jiǎn)單介紹一下unity3d中資源的處理種類(lèi)(歡迎拍磚):
小匹夫遇到過(guò)的大體就是如下幾種了旭贬,Resources、StreamingAssets搪泳、AssetBundle稀轨、PersistentDataPath,下面簡(jiǎn)單分析一下岸军。Resources
:
是作為一個(gè)Unity3D的保留文件夾出現(xiàn)的奋刽,也就是如果你新建的文件夾的名字叫Resources瓦侮,那么里面的內(nèi)容在打包時(shí)都會(huì)被無(wú)條件的打到發(fā)布包中。它的特點(diǎn)簡(jiǎn)單總結(jié)一下就是:
只讀杨名,即不能動(dòng)態(tài)修改脏榆。所以想要?jiǎng)討B(tài)更新的資源不要放在這里猖毫。
會(huì)將文件夾內(nèi)的資源打包集成到.asset文件里面台谍。因此建議可以放一些Prefab,因?yàn)镻refab在打包時(shí)會(huì)自動(dòng)過(guò)濾掉不需要的資源吁断,有利于減小資源包的大小趁蕊。
主線程加載。
資源讀取使用Resources.Load()仔役。
StreamingAssets
:
要說(shuō)到StreamingAssets掷伙,其實(shí)和Resources還是蠻像的。同樣作為一個(gè)只讀的Unity3D的保留文件夾出現(xiàn)又兵。不過(guò)兩者也有很大的區(qū)別任柜,那就是Resources文件夾中的內(nèi)容在打包時(shí)會(huì)被壓縮和加密。而StreamingAsset文件夾中的內(nèi)容則會(huì)原封不動(dòng)的打入包中沛厨,因此StreamingAssets主要用來(lái)存放一些二進(jìn)制文件宙地。下面也同樣做一個(gè)簡(jiǎn)單的總結(jié):
同樣,只讀不可寫(xiě)逆皮。
主要用來(lái)存放二進(jìn)制文件宅粥。
只能用過(guò)WWW類(lèi)來(lái)讀取。
AssetBundle
:
關(guān)于AssetBundle的介紹已經(jīng)有很多了电谣。簡(jiǎn)而言之就是把prefab或者二進(jìn)制文件封裝成AssetBundle文件(也是一種二進(jìn)制)秽梅。但是也有硬傷,就是在移動(dòng)端無(wú)法更新腳本剿牺。下面簡(jiǎn)單的總結(jié)下:
是Unity3D定義的一種二進(jìn)制類(lèi)型企垦。
最好將prefab封裝成AseetBundle,不過(guò)上面不是才說(shuō)了在移動(dòng)端無(wú)法更新腳本嗎晒来?那從Assetbundle中拿到的Prefab上掛的腳本是不是就無(wú)法運(yùn)行了钞诡?也不一定,只要這個(gè)prefab上掛的是本地腳本潜索,就可以臭增。
使用WWW類(lèi)來(lái)下載。
PersistentDataPath
:
看上去它只是個(gè)路徑呀竹习,可為什么要把它從路徑里面單獨(dú)拿出來(lái)介紹呢誊抛?因?yàn)樗拇_蠻特殊的,這個(gè)路徑下是可讀寫(xiě)整陌。而且在IOS上就是應(yīng)用程序的沙盒拗窃,但是在Android可以是程序的沙盒瞎领,也可以是sdcard。并且在Android打包的時(shí)候随夸,ProjectSetting頁(yè)面有一個(gè)選項(xiàng)Write Access九默,可以設(shè)置它的路徑是沙盒還是sdcard。下面同樣簡(jiǎn)單的總結(jié)一下:
內(nèi)容可讀寫(xiě)宾毒,不過(guò)只能運(yùn)行時(shí)才能寫(xiě)入或者讀取驼修。提前將數(shù)據(jù)存入這個(gè)路徑是不可行的。
無(wú)內(nèi)容限制诈铛。你可以從StreamingAsset
中讀取二進(jìn)制文件或者從AssetBundle
讀取文件來(lái)寫(xiě)入PersistentDataPath
中乙各。
寫(xiě)下的文件,可以在電腦上查看幢竹。同樣也可以清掉耳峦。
好啦,小匹夫介紹到這里焕毫,各位看官們是不是也都清楚了一些呢蹲坷?那么下面我們就開(kāi)始最后一步了,也就是如何在移動(dòng)平臺(tái)如何讀取外部文件邑飒。移動(dòng)平臺(tái)讀取外部文件的方法
上文小匹夫之所以要介紹Resources循签、StreamingAssets、AssetBundle幸乒、PersistentDataPath這四個(gè)東東懦底,就是因?yàn)樽x取外部資源的操作所涉及到的東西無(wú)外乎這幾種。既然是用Unity3D來(lái)開(kāi)發(fā)游戲罕扎,那么自然要使用Unity3D規(guī)定的操作方式聚唐,而不是我們?cè)赑C上很原始的那種操作方式來(lái)操作咯。否則就會(huì)像本文一開(kāi)始所演示的那樣腔召,寫(xiě)出移動(dòng)端無(wú)法使用的很傻的代碼來(lái)杆查。下面小匹夫就分別實(shí)現(xiàn)一下利用Resources、StreamingAssets臀蛛、AssetBundle來(lái)讀取的過(guò)程亲桦。Resources:
[C#] *純文本查看
*復(fù)制代碼
//用Resources讀取xml
using UnityEngine;
using System.Collections;
using EggToolkit;
using System.Xml.Linq;
using System.Xml;
public class Test : MonoBehaviour {
private string _result;
// Use this for initialization
void Start () {
LoadXML("Test");
}
// Update is called once per frame
void Update () {
}
private void LoadXML(string path)
{
_result = Resources.Load(path).ToString();
XmlDocument doc =new XmlDocument();
doc.LoadXml(_result);
}
void OnGUI()
{
GUIStyle titleStyle =new GUIStyle();
titleStyle.fon\= 20;
titleStyle.normal.textColor =newColor(46f/256f, 163f/256f, 256f/256f, 256f/256f);
GUI.Label(newRect(400, 10, 500, 200), _result,titleStyle);
}
}
結(jié)果如圖:OK抡柿,Resources讀取外部資源目標(biāo)達(dá)成L蚶拧!下面我們繼續(xù)洲劣,這次則是使用StreamingAssets來(lái)操作备蚓。StreamingAssets:
[C#] *純文本查看
*復(fù)制代碼
using UnityEngine;
using System.Collections;
using EggToolkit;
using System.Xml.Linq;
using System.Xml;
using System.IO;
public class Test : MonoBehaviour {
private string _result;
// Use this for initialization
void Start () {
StartCoroutine(LoadXML());
}
// Update is called once per frame
/// <summary>
/// 如前文所述横缔,streamingAssets只能使用www來(lái)讀取铺遂,
/// 如果不是使用www來(lái)讀取的同學(xué),就不要問(wèn)為啥讀不到streamingAssets下的內(nèi)容了茎刚。
/// 這里還可以使用了persistenDataPath來(lái)保存從streamingassets那里讀到內(nèi)容。
/// </summary>
IEnumerator LoadXML()
{
strings Path= Application.streamingAssetsPath +"/Test.xml";
WWW www =newWWW(sPath);
yield return www;
_result = www.text;
}
void
OnGUI(){
GUIStyle titleStyle =new GUIStyle();
titleStyle.fon\= 20;
titleStyle.normal.textColor =newColor(46f/256f, 163f/256f, 256f/256f, 256f/256f);
GUI.Label(newRect(400, 10, 500, 200), _result,titleStyle);
}
}
結(jié)果如圖:OK撤逢,StreamingAssets讀取外部資源目標(biāo)達(dá)成L哦А!下面我們繼續(xù)蚊荣,最后則是使用AssetBundle來(lái)操作初狰。AssetBundle:
來(lái)到AssetBundle,這里就和上面兩個(gè)不一樣了互例。首先我們要把我們的文件Test.xml打成AssetBundle文件奢入,由于小匹夫使用的是小米3作為測(cè)試機(jī),所以AssetBundle的平臺(tái)選擇為Andorid媳叨。如圖腥光,我們創(chuàng)建了一個(gè)AssetBundle文件,并命名為T(mén)extXML糊秆。并且按照二進(jìn)制文件放入StreamingAssets文件夾中的慣例武福,將這個(gè)AssetBundle文件放入StreamingAssets文件夾。[圖片上傳中痘番。捉片。。(7)]那么下面就是從AssetBudle中讀取Test.xml的內(nèi)容咯汞舱。直接上代碼:
[C#] *純文本查看
*復(fù)制代碼
//從AssetBundle中讀取xml
using EggToolkit;
using System.Xml.Linq;
using System.Xml;
using System.IO;
public class Test : MonoBehaviour {
private string _result;
// Use this for initialization
void Start () {
LoadXML();
}
// Update is called once per frame
void LoadXML()
{
AssetBundle AssetBundleCsv =newAssetBundle();
//讀取放入StreamingAssets文件夾中的bundle文件
string str = Application.streamingAssetsPath +"/"+"TestXML.bundle";
WWW www =newWWW(str);
www = WWW.LoadFromCacheOrDownload(str, 0);
AssetBundleCsv = www.assetBundle;
string path ="Test";
TextAsset test = AssetBundleCsv.Load(path,typeof(TextAsset))asTextAsset;
_result = test.ToString();
}
void OnGUI()
{
GUIStyle titleStyle =newGUIStyle();
titleStyle.fon\= 20;
titleStyle.normal.textColor =new Color(46f/256f, 163f/256f, 256f/256f, 256f/256f);
GUI.Label(newRect(400, 10, 500, 200), _result,titleStyle);
}
}
結(jié)果如圖:[圖片上傳中伍纫。。昂芜。(8)]OK莹规,AssetBundle讀取外部資源目標(biāo)也達(dá)成了!说铃!補(bǔ)充:
在此統(tǒng)一回答一下在評(píng)論和qq上有同學(xué)提出的一個(gè)問(wèn)題:
安卓上Application.persistentDataPath的內(nèi)容貌似不是匹夫你表里的那個(gè)呀访惜?
在本文的評(píng)論里小匹夫已經(jīng)回復(fù)過(guò)了嘹履,其實(shí)文中也說(shuō)過(guò)
前言:
一直有個(gè)想法,就是把工作中遇到的坑通過(guò)自己的深挖總結(jié)成一套相同[問(wèn)題
的解決方案供各位同行拍磚探討债热。眼瞅著2015年第一個(gè)工作日就要來(lái)到了砾嫉,小匹夫也休息的差不多了,尋思著也該寫(xiě)點(diǎn)東西活動(dòng)活動(dòng)大腦和手指了窒篱。那么今天開(kāi)始焕刮,小匹夫會(huì)記錄一些平時(shí)工作中遇到的坑,以及小匹夫的應(yīng)對(duì)方法墙杯,歡迎各位拍磚討論配并。那么今天主要討論一下[unity
3D在移動(dòng)端如何動(dòng)態(tài)的讀取外部文件,比如csv(txt),xml一類(lèi)的文件高镐。主要涉及的問(wèn)題溉旋,就是PC端上本來(lái)測(cè)試的好好的東西,到了移動(dòng)端就不能用了嫉髓,所以要討論一下PC端和移動(dòng)端的區(qū)別观腊,那么下一個(gè)問(wèn)題自然而然的就是移動(dòng)端的資源路徑(要討論一下Resources、StreamingAssets算行、AssetBundle梧油、PersistentDataPath),最后一步就是找到了資源如何讀戎菪稀(這里也會(huì)具體到對(duì)應(yīng)的幾種情況儡陨,即Resources、StreamingAssets量淌、AssetBundle)骗村,主要的思路就是這樣啦。對(duì)嘞类少,前言部分還是要祝各位看官新的一年身體健康叙身,升職加薪。假如我想在editor里動(dòng)態(tài)讀取文件
實(shí)際的游戲開(kāi)發(fā)中硫狞,其實(shí)有相當(dāng)一部分靜態(tài)數(shù)據(jù)是可以放在客戶(hù)端的信轿,所以勢(shì)必會(huì)產(chǎn)生要?jiǎng)討B(tài)讀取這些文件的需求,比如csv(其實(shí)就是文本文件)残吩,xml等等财忽。我相信大家不管是用win還是用mac來(lái)做[unity3d
的開(kāi)發(fā),都一定要先在editor中去實(shí)現(xiàn)基本的功能泣侮,在具體到各個(gè)移動(dòng)平臺(tái)上去調(diào)試即彪。所以作為要讀取外部文件的第一步,顯然我們要先在editor也就是pc上實(shí)現(xiàn)這個(gè)功能。下面給各位舉一個(gè)讀取xml的例子隶校,也是我在以前的一篇文章《自己動(dòng)手之使用反射和泛型漏益,動(dòng)態(tài)讀取XML創(chuàng)建類(lèi)實(shí)例并賦值》中使用過(guò)的,動(dòng)態(tài)讀取一個(gè)xml文件并動(dòng)態(tài)生成一個(gè)類(lèi)深胳。下面是我們用來(lái)做例子的xml文件绰疤,Test.xml:
[XML] *純文本查看
*復(fù)制代碼
<?xmlversion="1.0"encoding="UTF-8"?>
<test>
<name>chenjd</name>
<blog>http://www.cnblogs.com/murongxiaopifu/</blog>
<organization>Fanyoy</organization>
<age>25</age>
</test>
我們就可以很任性的把這個(gè)文件隨便丟在一個(gè)地方,只要你能指定對(duì)它的地址舞终。例如我還把它放在那篇文章中的地址Assets/xml-to-egg/xml-to-egg-test/
[C#] *純文本查看
*復(fù)制代碼
//讀取xml測(cè)試
using UnityEngine;
using System.Collections;
using EggToolkit;
using System.Xml.Linq;
public class Test : MonoBehaviour {
// Use this for initialization
void Start () {
XElement result = LoadXML("Assets/xml-to-egg/xml-to-egg-test/Test.xml");
//任性的地址
Debug.Log(result.ToString());
}
private
XElement LoadXML(string path)
{
XElement xml = XElement.Load(path);
return xml;
}
}
結(jié)果如下:結(jié)果是讀取成功了轻庆。但是你以為到這一步就成功了,那就錯(cuò)了敛劝。因?yàn)檫@樣的代碼到移動(dòng)端是行不通的余爆,至少2處可以被罵sb:
醉人的地址,地址參數(shù)那樣寫(xiě)就不用考慮跨平臺(tái)了夸盟。所以這個(gè)sb點(diǎn)引出的問(wèn)題就是在移動(dòng)端unity3d找不到目標(biāo)文件
蛾方。
使用的還是pc上傳統(tǒng)的一套讀取資源的做法,沒(méi)有使用unity3d提供的方法满俗,所以可能導(dǎo)致的問(wèn)題是找得到文件但是沒(méi)有正確的讀取文件內(nèi)容
转捕。
以上用紅色標(biāo)出的問(wèn)題,便是小匹夫想到的可能出現(xiàn)的問(wèn)題唆垃,也是下文要討論的內(nèi)容。那么我們首先來(lái)看看資源路徑在各個(gè)平臺(tái)上的不同之處吧痘儡。移動(dòng)平臺(tái)的資源路徑問(wèn)題
想要讀取一個(gè)文件辕万,自然首先要找到這個(gè)文件,下面小匹夫首先會(huì)總結(jié)一下unity3d中存在的各個(gè)地址沉删,之后再總結(jié)一下各個(gè)地址在各個(gè)移動(dòng)平臺(tái)中的對(duì)應(yīng)位置渐尿。Unity3D中的資源路徑
Application.dataPath
此屬性用于返回程序的數(shù)據(jù)文件所在文件夾的路徑。例如在Editor中就是Assets了矾瑰。
Application.streamingAssetsPath
此屬性用于返回流數(shù)據(jù)的緩存目錄砖茸,返回路徑為相對(duì)路徑,適合設(shè)置一些外部數(shù)據(jù)文件的路徑殴穴。
Application.persistentDataPath
此屬性用于返回一個(gè)持久化數(shù)據(jù)存儲(chǔ)目錄的路徑凉夯,可以在此路徑下存儲(chǔ)一些持久化的數(shù)據(jù)文件。
Application.temporaryCachePath
此屬性用于返回一個(gè)臨時(shí)數(shù)據(jù)的緩存目錄采幌。
[android
平臺(tái)
Application.dataPath
/data/app/xxx.xxx.xxx.apk
Application.streamingAssetsPath
jar:file:///data/app/xxx.xxx.xxx.apk/!/assets
Application.persistentDataPath
/data/data/xxx.xxx.xxx/files
Application.temporaryCachePath
/data/data/xxx.xxx.xxx/cache
IOS平臺(tái)
Application.dataPath
Application/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/xxx.app/Data
Application.streamingAssetsPath
Application/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/xxx.app/Data/Raw
Application.persistentDataPath
Application/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/Documents
Application.temporaryCachePath
Application/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/Library/Caches
從上面的3張表格劲够,我們可以看到 dataPath和streamingAssetsPath的路徑位置一般是相對(duì)程序的安裝目錄位置,而persistentDataPath和temporaryCachePath的路徑位置一般是相對(duì)所在系統(tǒng)的固定位置休傍。那么現(xiàn)在明確了unity3d中各個(gè)地址在不同平臺(tái)上的含義征绎,下一個(gè)問(wèn)題就來(lái)了,也就是我打包之后的資源要怎么和這些地址對(duì)應(yīng)上呢磨取?要知道在pc的editor里默認(rèn)的資源文件存放的路徑就是Assets啊人柿,為何又會(huì)派生出那么多路徑呢柴墩?那么就帶著這個(gè)疑問(wèn),和小匹夫一起進(jìn)行下文的內(nèi)容吧凫岖。簡(jiǎn)單介紹一下unity3d中資源的處理種類(lèi)(歡迎拍磚):
小匹夫遇到過(guò)的大體就是如下幾種了江咳,Resources、StreamingAssets隘截、AssetBundle扎阶、PersistentDataPath,下面簡(jiǎn)單分析一下婶芭。Resources
:
是作為一個(gè)Unity3D的保留文件夾出現(xiàn)的东臀,也就是如果你新建的文件夾的名字叫Resources,那么里面的內(nèi)容在打包時(shí)都會(huì)被無(wú)條件的打到發(fā)布包中犀农。它的特點(diǎn)簡(jiǎn)單總結(jié)一下就是:
只讀惰赋,即不能動(dòng)態(tài)修改。所以想要?jiǎng)討B(tài)更新的資源不要放在這里呵哨。
會(huì)將文件夾內(nèi)的資源打包集成到.asset文件里面赁濒。因此建議可以放一些Prefab,因?yàn)镻refab在打包時(shí)會(huì)自動(dòng)過(guò)濾掉不需要的資源孟害,有利于減小資源包的大小拒炎。
主線程加載。
資源讀取使用Resources.Load()挨务。
StreamingAssets
:
要說(shuō)到StreamingAssets击你,其實(shí)和Resources還是蠻像的。同樣作為一個(gè)只讀的Unity3D的保留文件夾出現(xiàn)谎柄。不過(guò)兩者也有很大的區(qū)別丁侄,那就是Resources文件夾中的內(nèi)容在打包時(shí)會(huì)被壓縮和加密。而StreamingAsset文件夾中的內(nèi)容則會(huì)原封不動(dòng)的打入包中朝巫,因此StreamingAssets主要用來(lái)存放一些二進(jìn)制文件鸿摇。下面也同樣做一個(gè)簡(jiǎn)單的總結(jié):
同樣,只讀不可寫(xiě)劈猿。
主要用來(lái)存放二進(jìn)制文件拙吉。
只能用過(guò)WWW類(lèi)來(lái)讀取。
AssetBundle
:
關(guān)于AssetBundle的介紹已經(jīng)有很多了糙臼。簡(jiǎn)而言之就是把prefab或者二進(jìn)制文件封裝成AssetBundle文件(也是一種二進(jìn)制)庐镐。但是也有硬傷,就是在移動(dòng)端無(wú)法更新腳本变逃。下面簡(jiǎn)單的總結(jié)下:
是Unity3D定義的一種二進(jìn)制類(lèi)型必逆。
最好將prefab封裝成AseetBundle,不過(guò)上面不是才說(shuō)了在移動(dòng)端無(wú)法更新腳本嗎?那從Assetbundle中拿到的Prefab上掛的腳本是不是就無(wú)法運(yùn)行了名眉?也不一定粟矿,只要這個(gè)prefab上掛的是本地腳本,就可以损拢。
使用WWW類(lèi)來(lái)下載陌粹。
PersistentDataPath
:
看上去它只是個(gè)路徑呀,可為什么要把它從路徑里面單獨(dú)拿出來(lái)介紹呢福压?因?yàn)樗拇_蠻特殊的掏秩,這個(gè)路徑下是可讀寫(xiě)。而且在IOS上就是應(yīng)用程序的沙盒荆姆,但是在Android可以是程序的沙盒蒙幻,也可以是sdcard。并且在Android打包的時(shí)候胆筒,ProjectSetting頁(yè)面有一個(gè)選項(xiàng)Write Access邮破,可以設(shè)置它的路徑是沙盒還是sdcard。下面同樣簡(jiǎn)單的總結(jié)一下:
內(nèi)容可讀寫(xiě)仆救,不過(guò)只能運(yùn)行時(shí)才能寫(xiě)入或者讀取抒和。提前將數(shù)據(jù)存入這個(gè)路徑是不可行的。
無(wú)內(nèi)容限制彤蔽。你可以從StreamingAsset
中讀取二進(jìn)制文件或者從AssetBundle
讀取文件來(lái)寫(xiě)入PersistentDataPath
中摧莽。
寫(xiě)下的文件,可以在電腦上查看顿痪。同樣也可以清掉范嘱。
好啦,小匹夫介紹到這里员魏,各位看官們是不是也都清楚了一些呢?那么下面我們就開(kāi)始最后一步了叠聋,也就是如何在移動(dòng)平臺(tái)如何讀取外部文件撕阎。移動(dòng)平臺(tái)讀取外部文件的方法
上文小匹夫之所以要介紹Resources、StreamingAssets碌补、AssetBundle、PersistentDataPath這四個(gè)東東,就是因?yàn)樽x取外部資源的操作所涉及到的東西無(wú)外乎這幾種求橄。既然是用Unity3D來(lái)開(kāi)發(fā)游戲钮莲,那么自然要使用Unity3D規(guī)定的操作方式,而不是我們?cè)赑C上很原始的那種操作方式來(lái)操作咯袜啃。否則就會(huì)像本文一開(kāi)始所演示的那樣汗侵,寫(xiě)出移動(dòng)端無(wú)法使用的很傻的代碼來(lái)。下面小匹夫就分別實(shí)現(xiàn)一下利用Resources、StreamingAssets晰韵、AssetBundle來(lái)讀取的過(guò)程发乔。Resources:
[C#] *純文本查看
*復(fù)制代碼
//用Resources讀取xml
using UnityEngine;
using System.Collections;
using EggToolkit;
using System.Xml.Linq;
using System.Xml;
public class Test : MonoBehaviour {
private string _result;
// Use this for initialization
void Start () {
LoadXML("Test");
}
private void LoadXML(string path)
{
_result = Resources.Load(path).ToString();
XmlDocument doc =newXmlDocument();
doc.LoadXml(_result);
}
void OnGUI()
{ GUIStyle titleStyle =newGUIStyle();
titleStyle.fon\= 20;
titleStyle.normal.textColor =newColor(46f/256f, 163f/256f, 256f/256f, 256f/256f);
GUI.Label(newRect(400, 10, 500, 200), _result,titleStyle);
}
}
結(jié)果如圖:OK只恨,Resources讀取外部資源目標(biāo)達(dá)成R胝獭!下面我們繼續(xù)官觅,這次則是使用StreamingAssets來(lái)操作纵菌。StreamingAssets:
[C#] *純文本查看
*復(fù)制代碼
using UnityEngine;
using System.Collections;
using EggToolkit;
using System.Xml.Linq;
using System.Xml;
using System.IO;
public class Test : MonoBehaviour {
private string _result;
// Use this for initialization
void Start () {
StartCoroutine(LoadXML());
}
// Update is called once per frame
/// <summary>
/// 如前文所述杠览,streamingAssets只能使用www來(lái)讀取,
/// 如果不是使用www來(lái)讀取的同學(xué)纵势,就不要問(wèn)為啥讀不到streamingAssets下的內(nèi)容了踱阿。
/// 這里還可以使用了persistenDataPath來(lái)保存從streamingassets那里讀到內(nèi)容。
/// </summary>
IEnumerator LoadXML()
{
stringsPath= Application.streamingAssetsPath +"/Test.xml";
WWW www =newWWW(sPath);
yieldreturnwww;
_result = www.text;
}
void OnGUI()
{
GUIStyle titleStyle =newGUIStyle();
titleStyle.fon\= 20;
titleStyle.normal.textColor =newnColor(46f/256f, 163f/256f, 256f/256f, 256f/256f);
GUI.Label(newRect(400, 10, 500, 200), _result,titleStyle);
}
}
結(jié)果如圖:OK钦铁,StreamingAssets讀取外部資源目標(biāo)達(dá)成H砩唷!下面我們繼續(xù)牛曹,最后則是使用AssetBundle來(lái)操作佛点。AssetBundle:
來(lái)到AssetBundle,這里就和上面兩個(gè)不一樣了黎比。首先我們要把我們的文件Test.xml打成AssetBundle文件超营,由于小匹夫使用的是小米3作為測(cè)試機(jī),所以AssetBundle的平臺(tái)選擇為Andorid阅虫。如圖演闭,我們創(chuàng)建了一個(gè)AssetBundle文件,并命名為T(mén)extXML颓帝。并且按照二進(jìn)制文件放入StreamingAssets文件夾中的慣例米碰,將這個(gè)AssetBundle文件放入StreamingAssets文件夾窝革。[圖片上傳中。见间。聊闯。(15)]那么下面就是從AssetBudle中讀取Test.xml的內(nèi)容咯。直接上代碼:
[C#] *純文本查看
*復(fù)制代碼
//從AssetBundle中讀取xml
using EggToolkit;
using System.Xml.Linq;
using System.Xml;
using System.IO;
public class Test : MonoBehaviour {
private string_ result;
void Start () {
LoadXML();
}
void LoadXML()
{
AssetBundle AssetBundleCsv =new AssetBundle();
//讀取放入StreamingAssets文件夾中的bundle文件
string str = Application.streamingAssetsPath +"/"+"TestXML.bundle";
WWW www =new WWW(str);
www = WWW.LoadFromCacheOrDownload(str, 0);
AssetBundleCsv = www.assetBundle;
string path ="Test";
TextAsset test = AssetBundleCsv.Load(path,typeof(TextAsset))asTextAsset;
_result = test.ToString();
}
void OnGUI()
{ GUIStyle titleStyle =newGUIStyle();
titleStyle.fon\= 20;
titleStyle.normal.textColor =new Color(46f/256f, 163f/256f, 256f/256f, 256f/256f);
GUI.Label(new Rect(400, 10, 500, 200), _result,titleStyle);
}
}
結(jié)果如圖:[圖片上傳中米诉。菱蔬。。(16)]OK史侣,AssetBundle讀取外部資源目標(biāo)也達(dá)成了K┟凇!補(bǔ)充:
在此統(tǒng)一回答一下在評(píng)論和qq上有同學(xué)提出的一個(gè)問(wèn)題:
安卓上Application.persistentDataPath的內(nèi)容貌似不是匹夫你表里的那個(gè)呀惊橱?
在本文的評(píng)論里小匹夫已經(jīng)回復(fù)過(guò)了蚪腐,其實(shí)文中也說(shuō)過(guò)