移動(dòng)平臺(tái)動(dòng)態(tài)讀取外部文件全解析

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/

文件夾下(的確很任性)
下面我們實(shí)現(xiàn)在PC上讀取這個(gè)文件內(nèi)容的代碼:

[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:

首先我們新建一個(gè)Resources目錄,并且將上面我們用到的Test.xml復(fù)制一份到這個(gè)文件夾中浊仆。如圖:
然后我們通過(guò)Resources的讀取方法來(lái)讀取Test.xml的內(nèi)容客峭。并且調(diào)用GUI將xml的內(nèi)容繪制出來(lái)。

[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:

同Resources一樣课蔬,我們要新建一個(gè)StreamingAssets的文件夾來(lái)存放我們的Test.xml文件。如圖:
不過(guò)前文已經(jīng)說(shuō)了郊尝,StreamingAssets文件夾內(nèi)的東西并不會(huì)被壓縮和加密二跋,而是放進(jìn)去什么就是什么,所以一般是要放二進(jìn)制文件的流昏,這里小匹夫僅僅做一個(gè)演示扎即,各位在實(shí)際操作中切記不要直接把數(shù)據(jù)文件放到這個(gè)目錄中打包。
[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/

文件夾下(的確很任性)
下面我們實(shí)現(xiàn)在PC上讀取這個(gè)文件內(nèi)容的代碼:

[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:

首先我們新建一個(gè)Resources目錄,并且將上面我們用到的Test.xml復(fù)制一份到這個(gè)文件夾中雪猪。如圖:
然后我們通過(guò)Resources的讀取方法來(lái)讀取Test.xml的內(nèi)容栏尚。并且調(diào)用GUI將xml的內(nèi)容繪制出來(lái)。

[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:

同Resources一樣,我們要新建一個(gè)StreamingAssets的文件夾來(lái)存放我們的Test.xml文件缰猴。如圖:
不過(guò)前文已經(jīng)說(shuō)了产艾,StreamingAssets文件夾內(nèi)的東西并不會(huì)被壓縮和加密,而是放進(jìn)去什么就是什么滑绒,所以一般是要放二進(jìn)制文件的闷堡,這里小匹夫僅僅做一個(gè)演示,各位在實(shí)際操作中切記不要直接把數(shù)據(jù)文件放到這個(gè)目錄中打包疑故。
[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ò)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市税朴,隨后出現(xiàn)的幾起案子回季,更是在濱河造成了極大的恐慌,老刑警劉巖正林,帶你破解...
    沈念sama閱讀 216,324評(píng)論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件泡一,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡觅廓,警方通過(guò)查閱死者的電腦和手機(jī)鼻忠,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,356評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)杈绸,“玉大人帖蔓,你說(shuō)我怎么就攤上這事⊥В” “怎么了塑娇?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,328評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)劫侧。 經(jīng)常有香客問(wèn)我钝吮,道長(zhǎng),這世上最難降的妖魔是什么板辽? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,147評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮棘催,結(jié)果婚禮上劲弦,老公的妹妹穿的比我還像新娘。我一直安慰自己醇坝,他們只是感情好邑跪,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,160評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布次坡。 她就那樣靜靜地躺著,像睡著了一般画畅。 火紅的嫁衣襯著肌膚如雪砸琅。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,115評(píng)論 1 296
  • 那天轴踱,我揣著相機(jī)與錄音症脂,去河邊找鬼。 笑死淫僻,一個(gè)胖子當(dāng)著我的面吹牛诱篷,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播雳灵,決...
    沈念sama閱讀 40,025評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼棕所,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了悯辙?” 一聲冷哼從身側(cè)響起琳省,我...
    開(kāi)封第一講書(shū)人閱讀 38,867評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎躲撰,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體茴肥,經(jīng)...
    沈念sama閱讀 45,307評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,528評(píng)論 2 332
  • 正文 我和宋清朗相戀三年瞬铸,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片础锐。...
    茶點(diǎn)故事閱讀 39,688評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖皆警,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情信姓,我是刑警寧澤鸵隧,帶...
    沈念sama閱讀 35,409評(píng)論 5 343
  • 正文 年R本政府宣布,位于F島的核電站豆瘫,受9級(jí)特大地震影響菊值,放射性物質(zhì)發(fā)生泄漏外驱。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,001評(píng)論 3 325
  • 文/蒙蒙 一磅崭、第九天 我趴在偏房一處隱蔽的房頂上張望瓦哎。 院中可真熱鬧,春花似錦杭煎、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,657評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至雷恃,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間旬痹,已是汗流浹背讨越。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,811評(píng)論 1 268
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留把跨,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,685評(píng)論 2 368
  • 正文 我出身青樓着逐,卻偏偏與公主長(zhǎng)得像崔赌,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子耸别,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,573評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理健芭,服務(wù)發(fā)現(xiàn)秀姐,斷路器,智...
    卡卡羅2017閱讀 134,651評(píng)論 18 139
  • 1吩翻、什么是AssetBundle AssetBundle 是Unity pro提供的一種用來(lái)存儲(chǔ)資源的文件格式锥咸,它...
    好怕怕閱讀 7,531評(píng)論 1 8
  • Unity3D 里有兩種動(dòng)態(tài)加載機(jī)制:一個(gè)是Resources.Load,另外一個(gè)通過(guò)AssetBundle,其實(shí)...
    IongX閱讀 1,725評(píng)論 0 5
  • 111. [動(dòng)畫(huà)系統(tǒng)]如何將其他類(lèi)型的動(dòng)畫(huà)轉(zhuǎn)換成關(guān)鍵幀動(dòng)畫(huà)熊锭? 動(dòng)畫(huà)->點(diǎn)緩存->關(guān)鍵幀 112. [動(dòng)畫(huà)]Unit...
    胤醚貔貅閱讀 13,012評(píng)論 3 90
  • 遍野欺霜寒瑟瑟碗殷,凄風(fēng)催展蕊含香速缨。 紅樓賦曲憐花淚,碧院調(diào)弦撫葉傷旬牲。 御賜珍珠冰吐艷,題詩(shī)舊帕雪凝妝吭历。 天然麗質(zhì)孤芳...
    半溪煙水閱讀 264評(píng)論 1 6