一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

細說Unity3D(一)動態(tài)讀取外部文件

 3dC 2015-07-01

前言:

一直有個想法,就是把工作中遇到的坑通過自己的深挖總結(jié)成一套相同問題的解決方案供各位同行拍磚探討。眼瞅著2015年第一個工作日就要來到了,小匹夫也休息的差不多了,尋思著也該寫點東西活動活動大腦和手指了。那么今天開始,小匹夫會記錄一些平時工作中遇到的坑,以及小匹夫的應(yīng)對方法,歡迎各位拍磚討論。那么今天主要討論一下Unity3D在移動端如何動態(tài)的讀取外部文件,比如csv(txt),xml一類的文件。主要涉及的問題,就是PC端上本來測試的好好的東西,到了移動端就不能用了,所以要討論一下PC端和移動端的區(qū)別,那么下一個問題自然而然的就是移動端的資源路徑(要討論一下Resources、StreamingAssets、AssetBundle、PersistentDataPath),最后一步就是找到了資源如何讀?。ㄟ@里也會具體到對應(yīng)的幾種情況,即Resources、StreamingAssets、AssetBundle),主要的思路就是這樣啦。對嘞,前言部分還是要祝各位看官新的一年身體健康,升職加薪。

假如我想在editor里動態(tài)讀取文件

實際的游戲開發(fā)中,其實有相當(dāng)一部分靜態(tài)數(shù)據(jù)是可以放在客戶端的,所以勢必會產(chǎn)生要動態(tài)讀取這些文件的需求,比如csv(其實就是文本文件),xml等等。我相信大家不管是用win還是用mac來做unity3d的開發(fā),都一定要先在editor中去實現(xiàn)基本的功能,在具體到各個移動平臺上去調(diào)試。所以作為要讀取外部文件的第一步,顯然我們要先在editor也就是pc上實現(xiàn)這個功能。

下面給各位舉一個讀取xml的例子,也是我在以前的一篇文章《 自己動手之使用反射和泛型,動態(tài)讀取XML創(chuàng)建類實例并賦值 》中使用過的,動態(tài)讀取一個xml文件并動態(tài)生成一個類。

下面是我們用來做例子的xml文件,Test.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>

我們就可以很任性的把這個文件隨便丟在一個地方,只要你能指定對它的地址。例如我還把它放在那篇文章中的地址 Assets/xml-to-egg/xml-to-egg-test/ 文件夾下(的確很任性)

下面我們實現(xiàn)在PC上讀取這個文件內(nèi)容的代碼:

//讀取xml測試
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é)果是讀取成功了。但是你以為到這一步就成功了,那就錯了。因為這樣的代碼到移動端是行不通的,至少2處可以被罵sb:

  1. 醉人的地址,地址參數(shù)那樣寫就不用考慮跨平臺了。所以這個sb點引出的問題就是在 移動端unity3d找不到目標(biāo)文件 。
  2. 使用的還是pc上傳統(tǒng)的一套讀取資源的做法,沒有使用unity3d提供的方法,所以可能導(dǎo)致的問題是找得到文件但是 沒有正確的讀取文件內(nèi)容 。

以上用紅色標(biāo)出的問題,便是小匹夫想到的可能出現(xiàn)的問題,也是下文要討論的內(nèi)容。那么我們首先來看看資源路徑在各個平臺上的不同之處吧。

移動平臺的資源路徑問題

想要讀取一個文件,自然首先要找到這個文件,下面小匹夫首先會總結(jié)一下unity3d中存在的各個地址,之后再總結(jié)一下各個地址在各個移動平臺中的對應(yīng)位置。

Unity3D中的資源路徑

Application.dataPath 此屬性用于返回程序的數(shù)據(jù)文件所在文件夾的路徑。例如在Editor中就是Assets了。
Application.streamingAssetsPath 此屬性用于返回流數(shù)據(jù)的緩存目錄,返回路徑為相對路徑,適合設(shè)置一些外部數(shù)據(jù)文件的路徑。
Application.persistentDataPath 此屬性用于返回一個持久化數(shù)據(jù)存儲目錄的路徑,可以在此路徑下存儲一些持久化的數(shù)據(jù)文件。
Application.temporaryCachePath 此屬性用于返回一個臨時數(shù)據(jù)的緩存目錄。

android平臺

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平臺

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的路徑位置一般是相對程序的安裝目錄位置,而persistentDataPath和temporaryCachePath的路徑位置一般是相對所在系統(tǒng)的固定位置。那么現(xiàn)在明確了unity3d中各個地址在不同平臺上的含義,下一個問題就來了,也就是我打包之后的資源要怎么和這些地址對應(yīng)上呢?要知道在pc的editor里默認(rèn)的資源文件存放的路徑就是Assets啊,為何又會派生出那么多路徑呢?那么就帶著這個疑問,和小匹夫一起進行下文的內(nèi)容吧。

簡單介紹一下unity3d中資源的處理種類(歡迎拍磚):

小匹夫遇到過的大體就是如下幾種了,Resources、StreamingAssets、AssetBundle、PersistentDataPath,下面簡單分析一下。

Resources:

是作為一個Unity3D的保留文件夾出現(xiàn)的,也就是如果你新建的文件夾的名字叫Resources,那么里面的內(nèi)容在打包時都會被無條件的打到發(fā)布包中。它的特點簡單總結(jié)一下就是:

  1. 只讀,即不能動態(tài)修改。所以想要動態(tài)更新的資源不要放在這里。
  2. 會將文件夾內(nèi)的資源打包集成到.asset文件里面。因此建議可以放一些Prefab,因為Prefab在打包時會自動過濾掉不需要的資源,有利于減小資源包的大小。
  3. 主線程加載。
  4. 資源讀取使用Resources.Load()。

StreamingAssets:

要說到StreamingAssets,其實和Resources還是蠻像的。同樣作為一個只讀的Unity3D的保留文件夾出現(xiàn)。不過兩者也有很大的區(qū)別,那就是Resources文件夾中的內(nèi)容在打包時會被壓縮和加密。而StreamingAsset文件夾中的內(nèi)容則會原封不動的打入包中,因此StreamingAssets主要用來存放一些二進制文件。下面也同樣做一個簡單的總結(jié):

  1. 同樣,只讀不可寫。
  2. 主要用來存放二進制文件。
  3. 只能用過WWW類來讀取。

AssetBundle:

關(guān)于AssetBundle的介紹已經(jīng)有很多了。簡而言之就是把prefab或者二進制文件封裝成AssetBundle文件(也是一種二進制)。但是也有硬傷,就是在移動端無法更新腳本。下面簡單的總結(jié)下:

  1. 是Unity3D定義的一種二進制類型。
  2. 最好將prefab封裝成AseetBundle,不過上面不是才說了在移動端無法更新腳本嗎?那從Assetbundle中拿到的Prefab上掛的腳本是不是就無法運行了?也不一定,只要這個prefab上掛的是本地腳本,就可以。
  3. 使用WWW類來下載。

PersistentDataPath:

看上去它只是個路徑呀,可為什么要把它從路徑里面單獨拿出來介紹呢?因為它的確蠻特殊的,這個路徑下是可讀寫。而且在IOS上就是應(yīng)用程序的沙盒,但是在Android可以是程序的沙盒,也可以是sdcard。并且在Android打包的時候,ProjectSetting頁面有一個選項Write Access,可以設(shè)置它的路徑是沙盒還是sdcard。下面同樣簡單的總結(jié)一下:

  1. 內(nèi)容可讀寫,不過只能運行時才能寫入或者讀取。 提前將數(shù)據(jù)存入這個路徑是不可行的。
  2. 無內(nèi)容限制。你可以從 StreamingAsset 中讀取二進制文件或者從 AssetBundle 讀取文件來寫入 PersistentDataPath 中。
  3. 寫下的文件,可以在電腦上查看。同樣也可以清掉。

好啦,小匹夫介紹到這里,各位看官們是不是也都清楚了一些呢?那么下面我們就開始最后一步了,也就是如何在移動平臺如何讀取外部文件。

移動平臺讀取外部文件的方法

上文小匹夫之所以要介紹Resources、StreamingAssets、AssetBundle、PersistentDataPath這四個東東,就是因為讀取外部資源的操作所涉及到的東西無外乎這幾種。既然是用Unity3D來開發(fā)游戲,那么自然要使用Unity3D規(guī)定的操作方式,而不是我們在PC上很原始的那種操作方式來操作咯。否則就會像本文一開始所演示的那樣,寫出移動端無法使用的很傻的代碼來。

下面小匹夫就分別實現(xiàn)一下利用Resources、StreamingAssets、AssetBundle來讀取的過程。

Resources:

首先我們新建一個Resources目錄,并且將上面我們用到的Test.xml復(fù)制一份到這個文件夾中。如圖:

然后我們通過Resources的讀取方法來讀取Test.xml的內(nèi)容。并且調(diào)用GUI將xml的內(nèi)容繪制出來。

//用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.fontSize = 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é)果如圖:

OK,Resources讀取外部資源目標(biāo)達成??!

下面我們繼續(xù),這次則是使用StreamingAssets來操作。

StreamingAssets:

同Resources一樣,我們要新建一個StreamingAssets的文件夾來存放我們的Test.xml文件。如圖:

不過前文已經(jīng)說了,StreamingAssets文件夾內(nèi)的東西并不會被壓縮和加密,而是放進去什么就是什么,所以一般是要放二進制文件的,這里小匹夫僅僅做一個演示,各位在實際操作中切記不要直接把數(shù)據(jù)文件放到這個目錄中打包。

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
  void Update () {
  }
  /// <summary>
  /// 如前文所述,streamingAssets只能使用www來讀取,
  /// 如果不是使用www來讀取的同學(xué),就不要問為啥讀不到streamingAssets下的內(nèi)容了。
  /// 這里還可以使用了persistenDataPath來保存從streamingassets那里讀到內(nèi)容。
  /// </summary>
  IEnumerator LoadXML()
  {
    string sPath= Application.streamingAssetsPath + "/Test.xml";
    WWW www = new WWW(sPath);
    yield return www;
    _result = www.text;
  }
  void OnGUI()
  {
    GUIStyle titleStyle = new GUIStyle();  
    titleStyle.fontSize = 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é)果如圖:

OK,StreamingAssets讀取外部資源目標(biāo)達成?。?/p>

下面我們繼續(xù),最后則是使用AssetBundle來操作。

AssetBundle:

來到AssetBundle,這里就和上面兩個不一樣了。首先我們要把我們的文件Test.xml打成AssetBundle文件,由于小匹夫使用的是小米3作為測試機,所以AssetBundle的平臺選擇為Andorid。

如圖,我們創(chuàng)建了一個AssetBundle文件,并命名為TextXML。并且按照二進制文件放入StreamingAssets文件夾中的慣例,將這個AssetBundle文件放入StreamingAssets文件夾。

那么下面就是從AssetBudle中讀取Test.xml的內(nèi)容咯。直接上代碼:

//從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 Update () {
  }
  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)) as TextAsset;
    _result = test.ToString();
  }
  void OnGUI()
  {
    GUIStyle titleStyle = new GUIStyle();  
    titleStyle.fontSize = 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é)果如圖:

OK,AssetBundle讀取外部資源目標(biāo)也達成了!!

這樣,我們就實現(xiàn)了幾種動態(tài)讀取外部文件的操作。各位看官是否看明白了呢?當(dāng)然文章倉促,還有很多不足,歡迎大家拍磚探討~

如果各位看官覺得文章寫得還好,那么就容小匹夫各位給點個“推薦”,謝啦~

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多

    日本黄色高清视频久久| 色婷婷国产熟妇人妻露脸| 大香蕉精品视频一区二区| 99久久精品国产日本| 日韩aa一区二区三区| 国产精品一区二区视频| 国产免费无遮挡精品视频 | 日本不卡视频在线观看| 国产一级特黄在线观看| 一区二区日本一区二区欧美| 九九热最新视频免费观看| 欧美黑人在线一区二区| 大尺度激情福利视频在线观看| 久久永久免费一区二区| 99久久婷婷国产亚洲综合精品| 一级片黄色一区二区三区| 福利在线午夜绝顶三级| 精品人妻一区二区三区四在线| 欧美91精品国产自产| 日本黄色高清视频久久| 国产精品熟女在线视频| 丁香六月啪啪激情综合区| 又大又长又粗又黄国产| 东京热男人的天堂久久综合| 九九热国产这里只有精品| 亚洲欧美黑人一区二区 | 国产一区日韩二区欧美| 亚洲精品成人福利在线| 日本av在线不卡一区| 日韩欧美91在线视频| 欧美三级不卡在线观线看| 久久国产成人精品国产成人亚洲| 免费在线成人激情视频| 国产高清精品福利私拍| 日韩一区中文免费视频| 亚洲av熟女一区二区三区蜜桃| 欧美日韩亚洲精品内裤| 欧美大粗爽一区二区三区| 国产精品欧美一区两区| 免费观看在线午夜视频| 成人亚洲国产精品一区不卡|