unity動態加載之AssetBundle原理

Assetbundle 是Unity Pro提供提供的功能,它可以把多個遊戲對象或者資源二進制文件封裝到Assetbundle中,提供了封裝與解包的方法使用起來很便利。

1.預設

         Assetbundle可以將Prefab封裝起來,這是多麼方便啊! 而且我也強烈建議大家將Prefab封裝成Assetbundle,因爲Prefab可以將遊戲對象身上帶的遊戲遊戲組件、遊戲腳本、材質都封裝在一起。當從服務器上將Assetbundle下載以後直接Instantiate就可以放入遊戲中。


         試想一下,如果只能將原始的二進制資源文件放在服務器上下載,當資源文件下載完畢後,需要動態的創建遊戲對象、然後動態的將腳本綁定在遊戲對象、動態的將貼圖賦予遊戲對象等等各種動態的操作。。所以強烈建議使用Prefa,不解釋!!!!!

   另外,我在舉個例子,因爲模型有可能會帶很多動畫文件,那麼這樣一組模型資源就可能是多個FBX 文件 和 若干png貼圖文件 材質文件。這時我只需要把原始模型放入Prefab中,它就會包含這個模型的所有組件、甚至包括它的動畫資源、貼圖。那麼如下圖所示,Mode就是模型的Prefab文件,那麼我僅僅只需要把Mode這個預設打包成Assetbundle即可。 當我在服務器上下載這個Assetbundle並且載入遊戲中就可以直接使用了,切換動畫、換貼圖都可以。。


2.二進制文件


       也並不是Assetbundle中全都要用預設,Assetbundle它也可以將二進制文件直接封裝在裏面,比如圖片、聲音、文本信息等等。




 3.場景文件





    在Unity中可以將一個場景保存在Scene中,Scene就會包含這個場景中的所有,那能不能把Scene也封裝成Assetbundle中?答案是能,但是它不能在移動平臺上用,因爲移動平臺上是不能更新腳本的,換句話來說就是即使將腳本綁定在Prefab中,然後下載Assetbundle後,所有腳本是不會執行的,後面說另外一種巧妙用法。




4.移動平臺





        上面MOMO已經將Assetbundle 的使用原理大致介紹了一下 ,我們在談談移動平臺。腳本不能更新是移動平臺下最大的傷,這就意味着開發者無法繞過App store和 google Play這種在線商店升級應用程序。唯一能做到的就是更新資源、舉個例子,遊戲中在處理版本升級時,一般會有個大版本號和一個小版本號,大版本號就是 2.0、3.0這種 版本需要在AppStore中更新,大版本主要是升級遊戲腳本,然後當小版本號,比如2.0.1 或2.0.2這種只是更新遊戲中的資源,通過自己遊戲的服務器就可以完成,通過Assetbundle在自己服務器上下載,然後適應在遊戲中。如果非要更新腳本,或不得不更新腳本那麼只能在Appstore或者google Play去更新大版本。




    移動平臺上不能更新腳本,那麼Prefab上綁定的腳本怎麼辦?在任何平臺上都可以把腳本添加到Prefab上,然後打包成Assetbundle,只有移動平臺上有點特殊,比如將Test.cs這條腳本綁定在Prefab中,最後程序通過服務器下載這個Assetbundle ,當載入工程中這條腳本是不會被執行的。




          但是如果本地工程有Test.cs這條腳本,那麼Unity會自動將這條腳本綁定在下載的Prefab中,並且他們執行的非常好。如果本地工程中沒有Test.cs這條腳本,那麼Prefab上的腳本是永遠都不會執行的。有時我們會在腳本中寫一些Public的變量,有可能不同的Prefab上綁定的是相同的腳本,只是Inspector 腳本中的public參數不同。別擔心這一點Assetbundle 中的Prefab也是沒問題,所以說只要大版本中的腳本沒問題,在小版本中只更新遊戲資源是一點問題都麼有的。




5.移動優化





        之前我們說過可以將遊戲中的某個遊戲對象封裝成Assetbundle,也可以將遊戲中的整個場景也封裝成Assetbundle。但是我認爲需要巧妙的使用封裝場景,因爲場景中肯定有很多公用的模型,如果打包場景的話那麼內存與size就是 公用模型的size * N個場景,想想其實挺恐怖的。其實我們可以巧妙的使用,首先把場景中公用的部分和私有的部分統統放入Unity, 然後烘培整個場景。 當場景烘培完畢後把公用的模型部分在拿出去,場景只只保留私有的模型。還可以做一個工具將公用模型在場景中的座標保存在XML中(每個場景文件會對應一個公用模型的XML信息),最後在將公用的模型分別封裝在別的Assetbundle中。




       服務器上提供每個場景的Assetbundle ,和公用模型的Assetbundle,一般公用模型的Assetbundle可以放在常駐內存中(可能使用頻繁、根據項目的不同而定)場景Assetbundle下載完畢後,現載入場景然後在根據場景對應的XML信息將公用模型部分動態的在添加到場景中,這樣就完成了一個場景的構建。




6.總結





對遊戲中所有資源進行打包,比如按類型分爲五個大部分  界面,模型,特效,聲音,場景,腳本。




界面部分:




公用資源包(可複用的資源包)和 每個界面獨有得資源包(不可複用的資源包)統一使用Prefab 打包成.assetbundle 二進制格式。




模型部分:




按角色分類,統一使用Prefab 打包成.assetbundle 二進制格式。 模型部分包括模型文件與動畫文件,每一個模型文件對應一組動畫文件。(如果模型需要換裝還需提供對應換裝的模型與貼圖) ,因爲unity4的重定向動畫不支持動態加載,所以目前不需要考慮 不同大小 不同規格 不同性別 的模型重定向動畫。




特效部分: 統一使用Prefab 打包成.assetbundle 二進制格式。 




聲音部分: 統一使用Prefab 打包成.assetbundle 二進制格式。 




場景部分:場景和前面的有點區別,場景需要導出烘培的光信息並且只能烘培場景之上永遠不動的模型,但是這些永遠不動的模型有可能會同時在多個場景中使用,所以場景烘培完畢後要把重複使用的對象刪除,(運行遊戲在動態的加載進來)場景中只保留該場景中永遠不會變的模型,以及烘培的光照信息。 打包場景後會生成.unity3D 二進制格式,它和 assetbundle 打包方式是不同的。(另外,也可以考慮 json xml 二進制 來動態組裝場景)。  




腳本部分:如果Prefab上是帶腳本打包Assetbundle的話  腳本是不會被運行的(移動平臺), 但是unity有一個技巧,Prefab上的腳本 如果本地有的話它會把本地的同名腳本綁定在Prefab對象上,它會很好的執行。 




Prefab打包技巧: Prefab打包時自身是不佔多少空間的 <=1KB  但是Prefab上是可以關聯  這五大部分 “界面,模型,特效,聲音,場景,腳本”以及在Hierarchy視圖中 座標/縮放/旋轉。 關聯這些信息以後就會很大,所以爲了避免資源的浪費盡量避免Prefab重複關聯。




一個prefab下面可以同時關聯多個遊戲對象 ,這裏舉個例子如果你的 Prefab下面放了一個模型 它的大小可能是500k  ,在 Prefab下面放了十個完全相同模型 它的大小可能是501k 。 如果Prefab下面放了兩個不同的模型,它的大小可能就會是 500k x 2 的size  ,也就是說Prefab與關聯的數量是無關的 。 




加密部分: assetbundle 是可以轉換成 字節數組 ,客戶端與服務器約定一組解密 字節數組的算法就可以實現資源加密。




大版本升級: 




unity的版本升級其實主要是升級主程序中的腳本。 因爲所有的資源都是assetbundle 和 .unity3d   這些資源放在本地或者服務器 解包的方式是完全一樣,所以理論上我們的主程序包的大小可以做到很小,可以很好設置把多少資源放在包裏 或者把所少資源放在服務器上。在運行的時候服務端應該把所有 assetbundle 和 .unity3d的資源文件的下載地址列表返回給客戶端。




小版本升級:




小版本升級也就是更新資源,因爲不能更新腳本, 在登陸的時候服務端應該把所有 assetbundle 和 .unity3d的資源文件的下載地址列表返回給客戶端。




還有個需要考慮的地方,比如現在大版本是2.0.0 ,小版本已經是2.0.5 ,用戶的手機上是一個1.5.0的包。 此時用戶在打開遊戲的時候 應當強制它去appstore中去下載大版本2.0.0 ,當用戶下載完畢後登陸游戲,此時服務器告訴客戶端現在已經是2.0.5的小版本了,這時候客戶端去下載對應小版本的所有  assetbundle 和 .unity3d文件地址列表。




增量更新:理論上增量更新是可行的。因爲unity不能更新腳本,所以在處理增量更新的話 需要在代碼中做可以兼容增量更新的可能。




 




因爲Assetbundle這塊的代碼比較多,我還是決定分成兩篇文章來寫,這篇文章先說原理、下篇文章說代碼。歡迎大家來討論!




前幾天我和Unity鑫哥聊天,他告訴我IOS上是無法運行時更新腳本、但是Android上是可以運行時更新腳本,我回家也試了一下但是沒能成功,後來我考慮即使成功了項目中我也不打算那麼做,因爲這樣Android和IOS 做起來的差別就太多了, 另外Unity商店中有一個處理運行時更新腳本的插件 unityLua 大家可以去研究研究。




 




本文固定鏈接: http://www.xuanyusong.com/archives/2373
轉載請註明: 雨鬆MOMO 2013年06月17日 於 雨鬆MOMO程序研究院 發表
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章