① Unity3d 使用Assetbundle合並項目的幾點注意
Unity3d中動態資源讀取,除了Resources.Load方式。還有就是Assetbundle。
Assetbundle的各方面介紹,這里就不在贅述,網上搜搜就一大片。但是,是不是什麼東西都能被打成Assetbundle呢?
基本上,引用到的資源,都能被打成Assetbundle。但是腳本和shader卻不一樣,雖然腳本和shader也能被導入Assetbundle。但是卻不能把源文件導入(如果Assetbundle中存的是腳本的源文件,那也就沒那麼多熱更新解決方案了)。最簡單的驗證方法,把一個項目的一個場景,導出Assetbundle,另一個項目讀取這個Assetbundle運行。會發現資源都導入了,卻沒有執行的腳本。
因此,如果兩個項目,想通過Assetbundle方式,來合並兩個項目,那就必須把腳本也拷到要被導入的項目中。兩個項目腳本合並,難免出現重名的腳本,重名的類。為了解決這個,每個項目,定一個唯一的namespace。如果項目開始的時候就定好了,那還好辦,如果後期合並,前期都沒加過。那就只能自己寫個Editor腳本,批量加上。
Unity項目中,難免使用一些全局的設置,比如,Physic重力設置,Tag和Layer這些。重力還好辦,項目運行起來,還能通過腳本修改。但是Tag,Layer卻不行。只能想辦法進行合並。
Unity中,Tag只能通過string修改。但是,導成Assetbundle之後,其存儲是index。所以要麼在合並Tag的時候,要麼批量修改,要麼寫個映射。當然,最好的方式是,項目統一用一套Tag。
Layer相比於Tag要簡單許多,Layer可以通過int修改。Unity最大有32個Layer,即使你不添加Layer,也能通過修改Layer的index來使用。那麼只要工程中定義全局使用的Layer即可
由於項目的資源都是Assetbundle,那麼打包的時候,Unity會自動幫你精簡項目。所以,Shader和腳本,就有可能被精簡掉。
所以保險起見,吧項目中所有的Shader全部添加到
Unity的腳本也得進行相應的設置
② 濡備綍鐏墊椿浣跨敤AssetBundle綆$悊CSS鏍峰紡鍙奐S鑴氭湰
2.0鐨勫彉鍖栫浉淇″ぇ瀹墮兘鐪嬪埌浜嗭紝鍏朵腑瀵逛竴涓璧勬簮鍖呮傚康鍋氬嚭浜嗗緢瀹岀編鐨勫疄鐜幫紝閭e氨鏄疉ssetBundle錛屼絾鏄寰堝氬垵瀛﹁呮湅鍙嬪彲鑳戒笉澶鑳藉熸g『鐨勯嗕細鍏朵腑鐨勫惈涔
鎴戠敾浜嗕竴寮犲浘錛屽ぇ瀹跺彲浠ュ皢灝辯湅涓涓嬶細
鍏朵腑錛屾帶鍒跺櫒鍔ㄤ綔鐨勮嗗浘錛坴iew錛夋覆鏌撻『搴忔槸浼樺厛浜庢垜浠鐨勬ā鏉塊〉錛坙ayout錛夌殑錛岄偅涔堜竴鏃︽垜浠鍦ㄦ煇涓瑙嗗浘涓浣跨敤浜嗘柊鐨凧S搴擄紝鎴栨柊鐨凜SS鏍峰紡鏂囦歡錛岄偅涔堟垜浠濡備綍鍘誨勭悊鍛錛
浠ヤ笅鏂瑰紡鏄閿欒鐨勶紝璇烽伩鍏嶄嬌鐢錛
鏈夌殑浜轟細鐩存帴鍦ㄨ嗗浘閲屾坊鍔犲筩ss鎴栬卝s鐨刲ink寮曠敤錛岃繖鏍峰紩鍏ョ殑鏂囦歡鏄鍦ㄨ嗗浘鍖哄煙錛岃寉ii鐨勯粯璁js鍔犺澆浼氭斁鍦ㄦā鏉塊〉鐨勬渶鍚庯紝榪欐牱鍙鑳藉艱嚧渚濊禆鍏崇郴娣蜂貢銆
姣斿備綘瑙嗗浘涓寮曠敤鐨刯s鏂囦歡閲岃皟鐢ㄤ簡jquery鍖咃紝浣嗘槸鎵ц屾椂jquery鐨勫姞杞戒唬鐮佸湪HTML欏甸潰鐨勬湯灝撅紝榪欐牱瀵艱嚧欏甸潰鑴氭湰閿欒銆
榪樻湁浜轟細鍥劇渷浜嬶紝鐩存帴鎶婇」鐩涓鎵鏈夌殑js鎴朿ss鏂囦歡閮戒功鍐檒ayout妯℃澘欏甸噷錛岃繖鏍蜂駭鐢熷ぇ閲忕殑鏃犳晥鏍峰紡鎴杍s錛屽獎鍝嶄簡鍔犺澆鏁堢巼鍙婇〉闈㈤敊浣嶉庨櫓銆
鎵浠ユg『鐨勬柟寮忓簲璇ユ槸閫氳繃AssetBundle鍘昏В鍐寵繖涓闂棰橈紝鍏堝彂涓涓綆鍗曠殑綾葷粰澶у剁湅涓涓嬶細
namespace app\assets;
use yii\web\AssetBundle;
class AppAsset extends AssetBundle {
public $basePath = '@webroot';
public $baseUrl = '@web';
public $css = [
'public/skin/default_skin/css/theme.css',
];
public $js = [
'public/vendor/jquery/jquery-1.11.1.min.js',
'public/vendor/jquery/jquery_ui/jquery-ui.min.js',
'public/js/bootstrap/bootstrap.min.js',
];
//渚濊禆鍖
public $depends = [
//榪欓噷鍐欎綘鐨勪緷璧栧寘鍗沖彲錛屾病鏈夊氨鍒鍐
];
//瀵煎叆褰撳墠欏電殑鍔熻兘js鏂囦歡錛屾敞鎰忓姞杞介『搴忥紝榪欎釜搴旇ユ渶鍚庤皟鐢
public static function addPageScript($view, $jsfile) {
$view->registerJsFile($jsfile, [AppAsset::className(), 'depends' => 'app\assets\AppAsset']);
}
//瀵煎叆緙栬緫鍣
public static function addCkeditor($view) {
$view->registerJsFile('/public/js/utility/ckeditor/ckeditor.js', [AppAsset::className(), 'depends' => 'app\assets\AppAsset']);
}
}
鍙浠ョ湅鍒頒笂闈㈡垜鍒涘緩鐨勭被涓宸茬粡棰勫畾涔変簡涓や釜闈欐佹柟娉昦ddPageScript鍜宎ddCkeditor錛屽叾涓璦ddCkeditor鏄涓涓絎涓夋柟鐨刯s緇勪歡錛屾槸涓緙栬緫鍣錛屽叿浣撶殑寮鍙戠幆澧冧腑浣犱滑鍙浠ュ啓鍒鐨勬柟娉曞悕鍙婂姞杞藉埆鐨勭粍浠躲
閭d箞涓婄殑榪欎釜涓滆タ鍐欏ソ鍚庡簲璇ュ備綍鍘諱嬌鐢ㄥ憿錛
鎴戜滑鍦ㄦā鏉塊〉寮澶撮儴鍒嗗姞涓婅繖鍙ヨ瘽錛
//鑷鍔ㄥ姞杞借祫婧
AppAsset::register($this);
榪欐牱浼氬湪妯℃澘欏靛姞杞藉熀紜鐨勯」鐩璧勬簮鏂囦歡錛屾瘮濡俢ss鍜宩s浠涔堢殑銆
鐜板湪鎴戜滑鏈変竴涓瑙嗗浘鍙玞reate-mail錛岄渶瑕佷嬌鐢╟keditor緙栬緫鍣錛岄偅涔堟垜浠搴旇ュ湪create-mail瑙嗗浘鐨勫紑澶村姞涓婅繖鍙ヨ瘽錛
//瀵煎叆ckeditor鍖呰祫婧
\app\assets\AppAsset::addCkeditor($this);
鏈鍚庤В閲婁竴涓嬶紝addCkeditor錛堬級鏂規硶鏄鎴戜滑棰勫厛瀹氫箟濂界殑錛岃繖鏍鋒垜浠鍙浠ユ妸涓浜涘父瑙佺殑鍖呴兘鎷嗗寘騫墮勫勭悊濂斤紝濡傛灉浣犺夊緱楹葷儲鍙浠ョ洿鎺ヤ嬌鐢ㄥ備笅鐨勬柟寮忥細
//瀵煎叆ckeditor鍖呰祫婧
\app\assets\AppAsset::addPageScript($this,'js鏂囦歡鐩稿硅礬寰勬垨url');
浠ヤ笂鐨勪緥瀛愬彧鏄浣跨敤浜唈s鏂囦歡浣滀負涓涓綆鍗曠殑浠嬬粛錛宑ss鏍峰紡鐨勫姞杞戒篃鏄涓鏍風殑閬撶悊銆
榪欐牱鍋氱殑濂藉勬槸錛屽嵆浣垮湪瑙嗗浘閲屽姞杞絚ss鎴杍s涔熶細鍥犱負渚濊禆鍏崇郴鑰屽嚭鐜板湪瑙嗗浘澶栭潰鐨勫父瑙勫姞杞藉尯鍩熶腑錛岃勮寖浜嗗緢澶氥
鍚屾椂涔熷洜涓轟緷璧栧叧緋伙紝浣犲湪瑙嗗浘閲屽姞杞界殑鏂囦歡鑲瀹氫細鎺掑湪浣犵殑鍩虹鏍峰紡鎴栬剼鏈鐨勫悗闈錛屼笉浼氬嚭閿欍
③ 如何做一個方便的資源管理方案
工具:
Unity 中的資源來源有三個途徑:一個是Unity自動打包資源,一個是Resources,一個是AssetBundle。
Unity自動打包資源是指在Unity場景中直接使用到的資源會隨著場景被自動打包到游戲中,這些資源會在場景載入的時候由unity自動載入。這些資源只要放置在Unity工程目錄的Assets文件夾下即可,程序不需要關心他們的打包和載入,這也意味著這些資源都是靜態載入的。但在實際的游戲開發中我們一般都是會動態創建GameObject,資源是動態載入的,因此這種資源其實不多。
Resources資源是指在Unity工程的Assets目錄下面可以建一個Resources文件夾,在這個文件夾下面放置的所有資源,不論是否被場景用到,都會被打包到游戲中,並且可以通過Resources.Load方法動態載入。這是平時開發是常用的資源載入方式,但是缺點是資源都直接打包到游戲包中了,沒法做增量更新。
AssetBundle資源是指我們可以通過編輯器腳本來將資源打包成多個獨立的AssetBundle。這些AssetBundle和游戲包是分離的,可以通過WWW類來載入。AssetBundle的使用很靈活:可以用來做分包發布,例如大多數頁游資源是隨著游戲的過程增量下載的,或者有些手游資源過大,渠道要求發布的包限制在100M以內,那隻能把一開始玩不到的內容做成增量包,等玩家玩到的時候通過網路下載。AssetBundle 也可以用來做我們下面討論的自動增量更新。
Unity5相比之前的版本,AssetsBundle的打包過程有所簡化。之前打包需要通過代碼來設置需要打入包的資源並自己建立包的依賴關系,Unity5可以通過每個資源Inspector底部的AssetBundle下拉來指定該資源要打入哪個包,不指定就是不打包。打包過程只需要BuildPipeline.BuildAssetBundles一句話就行了,Unity5會根據依賴關系自動生成所有的包。每個包還會生成一個manifest文件,這個文件描述了包大小、crc驗證、包之間的依賴關系等等,通過這個manifest打包工具在下次打包的時候可以判斷哪些包中的資源有改變,只打包資源改變的包,加快了打包速度。manifest只是打包工具自己用的,發布包的時候並不需要。
關於自動生成依賴關系這個有必要提下,Unity確實會自動給你建立依賴關系,前提是你依賴的資源必須已經在Inspector中設置了BundleName。如果沒有,Unity會把這個公用的資源重復打到多個用到的包中,因為這個公用資源不在一個獨立的包中,Unity也不會智能地給你發現它是公用的,然後生成一個公用包。更深的坑在於,如果你公用的是一個FBX模型,你只給這個模型設置BundleName還不行,它用到的貼圖,材質都要設,否則模型是公用了,貼圖沒有公用,結果貼圖還是被打包到多個包中了。所以設置BundleName這個工作最好還是由編輯器腳本來完成。
方案:
Unity提供的就這些了,下面就自己發揮:如何做一個方便的資源管理方案,既可以開發時方便,又可以方便發布更新包呢?開發過程全用AssetsBundle是不合適的,因為開發中資源經常添加和更新,每次添加或者更新都生成一下AssetsBundle才能運行是很麻煩的。而且我們要做的是自動更新而不是分包下載,這也就是說在發布游戲的時候這些資源應該都是在游戲包中的,所以他們也不該從AssetsBundle載入。
分析完需求,方案也就出來了:資源還是放在Resources下面,但是這些資源同時也會打包到AssetBundle中。代碼中所有載入資源的地方都通過自己的ResourceManager來載入,由ResourceMananger來決定是調用Resources.Load來載入資源還是從AssetsBundle載入。在開發環境下(Editor)這些資源顯然是直接從Resources載入的,發布的完整安裝包資源也是從Resources載入,只有當有一個增量版本時,游戲主程序才會去伺服器把增量的AssetBundle下載下來,然後從AssetBundle載入資源。
實現:
實現中我們首先要考慮的是AssetBundle的粒度,即每個AssetBundle包含多少資源。增量包的最小粒度就是AsssetBundle, 如果單個AssetBundle過大,只要這個AssetBundle中有一個資源改變了就需要重新下載整個AssetBundle,浪費流量和玩家的等待時間;如果單個AssetBundle過小,極端情況是每個資源一個AssetBundle,雖然實現了更新最小化,但是帶來了額外開銷:AssetBundle本身也是有大小的,而且查找載入AssetBundle也是需要時間的。大家都往U盤裡面拷過東西,拷一個1G的文件比拷1千個1M的文件要快很多。比較合理的做法是根據邏輯來,例如每個角色可以有獨立的AssetBundle,公用的一些UI資源可以打到一個AssetBundle裡面,每個場景獨立的UI資源可以打成獨立的AssetBundle。這樣做資源預載入的時候也方便,每個場景需要用到幾個Bundle就載入幾個Bundle,無關的資源不會被載入。