咱們在編輯器中看到的資源,在構建以後會進行一些轉化,本章將揭開Creator對資源進行的處理。html
首先咱們將Creator的開發和運行劃分爲如下幾個場景:node
當咱們將資源放到編輯器中時,Creator會爲每一個資源生成惟一的uuid以及meta文件,並在項目的library目錄下生成對應的json文件來描述這個資源的信息,而uuid與資源的映射關係被放在library目錄下的uuid-to-mtime.json文件中。因爲資源的引用關係是靠uuid來維繫的,因此咱們能夠在Creator中隨意地修改資源文件名、移動資源路徑,而不用擔憂資源的關聯丟失問題。算法
咱們在編輯器中編輯的prefab、anim、場景等文件本質上是一個json文件,Cocos Creator 設計了一套json規則用於描述各類資源,prefab的json描述了prefab的結構以及每一個節點的屬性,但部分屬性會放到meta文件中,通常是針對該資源在編輯器中的設置。json
預覽的時候使用的是library目錄下的資源,不只僅是項目assets目錄下的全部資源(包括未被引用到的資源),引擎提供的一些默認資源也能夠在library目錄下找到。預覽的模板位於引擎安裝目錄下的resources/static/preview-templates,程序的啓動腳本爲boot.js。數組
項目構建以後,資源會從library目錄下移動到構建輸出的目錄中,基本只會導出參與構建的場景和resources目錄下的資源,及其引用到的資源。腳本資源會由多個js腳本合併爲一個js,各類json文件也會按照特定的規則進行打包(所謂的packAssets)。async
圖片的meta文件大概以下所示,除了ver和uuid以外,還有3個屬性:編輯器
這裏的subMetas描述了一個SpriteFrame信息,詳情可參考Sprite組件工具
{ "ver": "2.0.0", "uuid": "a0576798-bdf4-4f06-972e-5557dee6ee1b", "type": "sprite", "wrapMode": "clamp", "filterMode": "bilinear", "subMetas": { "boss_b_hp1": { "ver": "1.0.3", "uuid": "5425ad9a-e2e0-4c6e-825b-c3ea43b09e4e", "rawTextureUuid": "a0576798-bdf4-4f06-972e-5557dee6ee1b", "trimType": "auto", "trimThreshold": 1, "rotated": false, "offsetX": 0, "offsetY": 0, "trimX": 0, "trimY": 0, "width": 78, "height": 78, "rawWidth": 78, "rawHeight": 78, "borderTop": 0, "borderBottom": 0, "borderLeft": 0, "borderRight": 0, "subMetas": {} } } }
這樣的一個圖片會在library/imports/xx目錄下生成3個文件(若是將圖片的type設置爲raw則不會有SpriteFrame對應的json文件),分別是以圖片uuid爲文件名的json文件和png,以及SpriteFrame的uuid爲文件名的json文件。性能
Texture對應的json文件內容以下,每個紋理都會生成一個這樣的重複的文件:字體
{ "__type__": "cc.Texture2D", "content": "0" }
SpriteFrame對應的json文件內容以下:
{ "__type__": "cc.SpriteFrame", "content": { "name": "boss_b_hp1", "texture": "a0576798-bdf4-4f06-972e-5557dee6ee1b", "atlas": "", "rect": [ 0, 0, 78, 78 ], "offset": [ 0, 0 ], "originalSize": [ 78, 78 ] } }
在構建以後,資源會被導出到res目錄下,json文件放在import目錄下,png等資源文件放在raw-assets目錄。
圖集分爲plist和圖片兩個文件,圖集圖片的meta和普通圖片的meta同樣,而plist文件的meta記錄了圖集中全部碎圖的信息。主要有ver、uuid、rawTextureUuid、size、type以及subMetas等屬性,subMetas記錄了每個碎圖的meta信息,結構和普通圖片的meta同樣。
{ "ver": "1.2.4", "uuid": "315d61c8-b6c8-4635-b517-f868dd8b3495", "rawTextureUuid": "01979186-b9a2-4130-a307-a2eacb5fe30f", "size": { "width": 1024, "height": 1024 }, "type": "Texture Packer", "subMetas": { "role1001-move1.png": { "ver": "1.0.3", "uuid": "8e225dbc-7905-416f-a7ac-0730893ad30d", "rawTextureUuid": "01979186-b9a2-4130-a307-a2eacb5fe30f", "trimType": "auto", "trimThreshold": 1, "rotated": false, "offsetX": 0, "offsetY": -52, ...
在library目錄下會生成plist的json文件,type爲cc.SpriteAtlas,記錄了圖集中全部spriteFrames的uuid,每個碎圖都會有一個描述其SpriteFrame的json文件生成。最後,圖片文件照常會有一個Texture和SpriteFrame的json生成。
{ "__type__": "cc.SpriteAtlas", "_name": "role1001.plist", "_objFlags": 0, "_native": "", "_spriteFrames": { "role1001-move1": { "__uuid__": "8e225dbc-7905-416f-a7ac-0730893ad30d" }, "role1001-move2": { "__uuid__": "7e0641ef-5974-4c2d-bad3-80c59a3195d8" }, ...
構建以後,cc.SpriteAtlas與全部的cc.SpriteFrame會合爲一個json,而圖片自己仍然會導出cc.Texture和cc.SpriteFrame的json。
【合併初始場景依賴的全部json】會讓全部用到的json都合併成一個。【內聯全部SpriteFrame】會將全部用到的SpriteFrame的json信息複製到引用它們的場景或prefab的json中,若是是單獨的一個SpriteFrame,會被直接合並。(這種狀況下,其餘場景加載該資源時如何處理?即該資源已經被打包到其餘場景或prefab中。多個prefab同時引用時誰能打包到該資源呢?加載一個打包資源中的一個json,是否會直接加載該json包中的全部json)
AutoAtlas能夠自動將當前目錄以及子目錄下全部的圖片進行合圖,他的meta文件描述了合圖的規則,如最大尺寸、是否容許旋轉、是否強制圖片轉爲正方形、尺寸是否爲2的冪、使用的合圖算法等等...
{ "ver": "1.1.0", "uuid": "691bdbcd-78c9-41da-864f-481d1af5c8ff", "maxWidth": 1024, "maxHeight": 1024, "padding": 2, "allowRotation": true, "forceSquared": false, "powerOfTwo": true, "heuristices": "BestAreaFit", "format": "png", "quality": 80, "contourBleed": false, "paddingBleed": false, "filterUnused": false, "subMetas": {} }
而在library目錄下,AutoAtlas只會生成一個簡單的json文件,在預覽的時候,AutoAtlas不會發生任何做用。
{ "__type__": "cc.SpriteAtlas", "_name": "AutoAtlas" }
構建以後,會生成cc.SpriteAtlas類型的一個json文件,記錄全部碎圖的uuid。AutoAtlas所在目錄下的碎圖會合成一張,而它們的SpriteFrame信息則不會像plist圖集同樣合併到圖集的json文件中,而是每一個SpriteFrame一個json文件。
{ "__type__": "cc.SpriteAtlas", "_spriteFrames": { "building_01": { "__uuid__": "d47RnkKqBHw6xXpAKXUDWt" }, "building_02": { "__uuid__": "a8CDt9ghBA5LzcZdD79OcY" }, "building_03": { "__uuid__": "f4JnL6lkFFjZC9QkBYLbZM" }, "building_04": { "__uuid__": "0cwdvX5/pBXYpf4xhZG+I+" }, "building_05": { "__uuid__": "64GzrRUetDzreLftZ9Unt5" } } }
場景和prefab相似,都是用一個json文件來描述節點樹。json文件首先描述一個數組,數組的第一個元素(下標0)描述的是該資源的類型以及該資源特定的屬性,接下來是一個一個的節點、組件對象,每一個對象都描述了自身的各類屬性,以及它們和其它對象的關係,其中的__id__字段對應的值表示當前json數組的下標。
[ // 數組的第一個元素,資源概述 { "__type__": "cc.prefab", // 類型,場景的__type__爲cc.SceneAsset "_name": "", "_objFlags": 0, "_native": "", "data": { // 數據(該prefab的根節點id),場景爲scene字段 "__id__": 1 }, "optimizationPolicy": 0, // 建立優化策略(場景無該選項) "asyncLoadAssets": false // 是否開啓延遲加載資源(場景無該選項) }, // 數組的第二個元素,prefab的根節點,其name爲Base,有2個子節點,id爲2和5 { "__type__": "cc.Node", "_name": "Base", "_objFlags": 0, "_parent": null, "_children": [ { "__id__": 2 }, { "__id__": 5 } ], "_tag": -1, "_active": true, "_components": [], "_prefab": { "__id__": 8 }, "_id": "", "_opacity": 255, "_color": { "__type__": "cc.Color", "r": 255, "g": 255, "b": 255, "a": 255 }, "_cascadeOpacityEnabled": true, "_anchorPoint": { "__type__": "cc.Vec2", "x": 0.5, "y": 0.5 }, "_contentSize": { "__type__": "cc.Size", "width": 0, "height": 0 }, "_rotationX": 0, "_rotationY": 0, "_scaleX": 1, "_scaleY": 1, "_position": { "__type__": "cc.Vec2", "x": 0, "y": 0 }, "_skewX": 0, "_skewY": 0, "_localZOrder": 0, "_globalZOrder": 0, "_opacityModifyRGB": false, "groupIndex": 0 }, { ... }, // Sprite組件的數據,它掛載在本數組中下標爲2的Node上(第三個元素) { "__type__": "cc.Sprite", "_name": "", "_objFlags": 0, "node": { "__id__": 2 }, "_enabled": true, "_spriteFrame": { // 全部的__uuid__都指向了一個新的資源 "__uuid__": "d4ed19e4-2aa0-47c3-ac57-a402975035ad" }, "_type": 0, "_sizeMode": 1, "_fillType": 0, "_fillCenter": { "__type__": "cc.Vec2", "x": 0, "y": 0 }, "_fillStart": 0, "_fillRange": 0, "_isTrimmedMode": true, "_srcBlendFactor": 770, "_dstBlendFactor": 771, "_atlas": null }, { "__type__": "cc.prefabInfo", "root": { "__id__": 1 }, "asset": { "__id__": 0 }, "fileId": "acUWY0/UZLeZdVqtcRkZuq", "sync": false }, ... ]
// 組件的__type__爲腳本的23位uuid "_components": [ { "__type__": "b8386waIgRGVJwXT7yno4pm", "node": { "__id__": 1 }, // myRootNode和mySpriteFrame爲腳本中的2個變量,在屬性檢查器中拖拽的 "myRootNode": { // myRootNode記錄着當前prefab中id爲2的節點 "__id__": 2 }, "mySpriteFrame": { // mySpriteFrame記錄着一個外部的SpriteFrame的uuid "__uuid__": "40t3EpX7tCnq5b2lM2bG8F" }, } ],
Scene和prefab對應的meta文件比較簡單,prefab包含了建立優化策略選項,Scene包含了是否自動釋放資源選項,他們都包含了是否延遲加載資源的選項。大體以下所示:
// prefab的meta文件內容 { "ver": "1.0.0", "uuid": "c7d921c2-6021-4613-93bd-6201de418e24", "optimizationPolicy": "AUTO", "asyncLoadAssets": false, "subMetas": {} } // scene文件的meta文件內容 { "ver": "1.0.0", "uuid": "2afc2a6e-f61e-4f46-8a52-af34d838a4b0", "asyncLoadAssets": false, "autoReleaseAssets": false, "subMetas": {} }
在library目錄下,以及構建目錄中,prefab和scene基本是json文件自己內容的一個複製。可能會根據prefab和scene的選項稍微修改json數組首元素的內容(好比添加asyncLoadAssets字段)。
Creator動畫保存在anim文件中,每個anim都是一個動畫Clip。咱們能夠在Creator中的資源管理器右鍵/新建/Animation Clip來建立新的anim動畫文件。要使用動畫咱們須要爲一個節點掛載Animation組件,而後將anim文件拖拽到Animation組件的clips屬性中。關於Creator動畫的更多詳情能夠參考官方文檔 https://docs.cocos.com/creator/manual/zh/animation/ 。
anim文件本質是一個json文件,它的內容大體以下,除了Creator標準的json字段,以及Clip的全局屬性(wrapMode、speed等)外,curveData字段記錄全部的動畫信息,events字段記錄了該動畫中全部的幀事件。它的meta文件只記錄了ver、uuid以及一個空的subMetas。
{ "__type__": "cc.AnimationClip", "_name": "1", "_objFlags": 0, "_native": "", "_duration": 0.25, "sample": 60, "speed": 1, "wrapMode": 1, "curveData": { "paths": { "build_b_2": { "props": { "position": [ { "frame": 0, "value": [ 39, 29 ] }, { "frame": 0.25, "value": [ 109, 29 ] } ] } } } }, "events": [ { "frame": 0.25, "func": "", "params": [] } ] }
該文件會被直接拷貝到library目錄下,構建以後會直接導出該文件。
聲音音效資源的meta文件很是簡單,目前惟一的一個自定義屬性就是downloadMode,即聲音的加載模式,有Web Audio和DOM Audio兩種。前者兼容性更好,但會佔用更多的內存,故建議短音效用Web Audio,長音樂使用DOM Audio。
{ "ver": "2.0.0", "uuid": "ab548e86-4fca-4320-a8a0-0c1a714d1443", "downloadMode": 0, "subMetas": {} }
在library目錄下,Creator會爲每一個聲音資源生成一個以uuid爲命名的json文件,以及將聲音文件以uuid命名。json文件的內容以下:
{ "__type__": "cc.AudioClip", "_name": "music_logo", "_objFlags": 0, "_native": ".mp3", "loadMode": 0 }
構建以後library目錄下的json和聲音文件會被複制到構建目錄下的import和raw-assets目錄中。
每一個Spine都是由json(Creator暫時不支持skel格式)、atlas、png三個文件組成,它們的meta文件很是簡單,沒有什麼特殊的信息。
在library目錄下,png會生成對應的SpriteFrame和Texture的json,以及圖片自身。atlas會生成一個簡單的json文件,以下所示。骨骼json會進行轉換,變成Creator標準的資源格式json,以uuid命名,在當前目錄下會建立一個以uuid命名的目錄,放着轉換前的Spine json文件,名爲raw-skeleton.json。(Creator格式的json比原Spine的json要大很多)
{ "__type__": "cc.Asset", "_name": "raptor", "_native": ".atlas" }
構建以後,png對應的SpriteFrame、Texture的json,以及Atlas的json。Spine自己的json會轉換成Creator標準的資源格式json輸出到構建目錄下,並且raw-skeleton.json並不在構建目錄中。
在Creator中支持TS和JS腳本,這裏不討論如何編寫腳本。腳本的meta文件中有幾個有意思的屬性,與Plugin相關,意爲是否將該腳本做爲插件導入。對第三方插件或者底層插件,有可能須要選中Plugin選項,這樣的腳本簡稱插件腳本(未勾選該選項的爲普通腳本)。腳本插件在打包時是不會參與構建的。
關於該選項的詳細介紹能夠查看 https://docs.cocos.com/creator/manual/zh/scripting/plugin-scripts.html 。
{ "ver": "1.0.5", "uuid": "8c87839a-4fd0-4b9e-9363-23bbf1bd16ef", "isPlugin": false, "loadPluginInWeb": true, "loadPluginInNative": true, "loadPluginInEditor": false, "subMetas": {} }
在library目錄下,TS會被編譯成JS腳本,全部的JS腳本都會以其uuid命名存儲。與JS文件一塊兒生成的還有map文件(這裏放着編譯前的原文件內容和路徑等相關信息)。
構建以後全部的TS和JS腳本會被編譯成JS,打包到一個project.dev.js文件中。構建通常會生成4個js,記錄全部資源相關設置的settings.js,啓動腳本main.js,開發者的代碼project.dev.js以及cocos引擎cocos2d-js.js。若是開啓了調試模式,構建出來的js會被精簡爲一行,剔除全部的註釋和空行換行,並自動將一些變量名進行混淆,使用更簡短的命名,而不影響代碼執行的效果。若是開啓了Source Maps,構建代碼時會生成map文件,不然不會生成。
咱們能夠在Creator編輯器中的項目菜單/項目設置/模塊設置下選擇剔除咱們不須要用到的模塊,從而精簡cocos2d-js.js文件的大小(新一代的js打包工具如rollup.js已經能夠支持到在打包的時候自動根據引用到的代碼去剔除無用代碼)。
CocosCreator的字體能夠分爲3類,系統字、BMFont以及TTF字體。系統字不須要額外的字體資源,而是使用內置的系統字體。BMFont的資源是一張圖片以及一個fnt。而TTF字體的資源是一個TTF文件。
fnt資源的meta文件以下所示,指定了fontSize,以及使用的紋理。
{ "ver": "2.1.0", "uuid": "e2fd9257-452a-4ae2-a932-e567c5fd6e91", "textureUuid": "1afd96d7-225c-484b-ab27-fe12902096d6", "fontSize": 32, "subMetas": {} }
在library目錄下,除了圖片相關的Texture、SpriteFrame等json。fnt文件會被轉成一個cc.BitmapFont的json文件,文件內容以下所示,_fntConfig描述了fnt字體的字號、寬高、圖集以及每個字在圖集中的座標尺寸等信息。
{ "__type__": "cc.BitmapFont", "_name": "b0", "_objFlags": 0, "_native": "", "fntDataStr": "", "spriteFrame": { "__uuid__": "a3e89811-562f-4a58-943f-895c807f087b" }, "fontSize": 32, "_fntConfig": { "commonHeight": 32, "fontSize": 32, "atlasName": "b0_0.png", "fontDefDictionary": { "36": { "rect": { "x": 81, "y": 0, "width": 79, "height": 111 }, "xOffset": 0, "yOffset": 0, "xAdvance": 79 }, ...
構建以後,cc.BitmapFont和SpriteFrame這2個json會被合併(咱們每每須要同時使用到它們)。
TTF的meta文件只有ver、uuid和空的subMetas字段。在library目錄下會生成一個以TTF資源的uuid命名的json文件,在相同目錄下有一個以TTF資源的uuid目錄,目錄下放着ttf資源。
{ "__type__": "cc.TTFFont", "_name": "BlackHanSans-Regular", "_objFlags": 0, "_native": "BlackHanSans-Regular.ttf" }
構建後該json文件會剔除_objFlags字段後導出,而TTF文件會導出到raw-assets目錄下。
粒子資源大體能夠分爲plist和prefab兩種:
{ "__type__": "cc.ParticleAsset", "_name": "p_star_fly", "_objFlags": 0, "_native": ".plist", "texture": { "__uuid__": "1544eed3-42e4-46fc-a392-0c4d8b1b9847" } }
在瞭解了Creator對單個資源的處理以後,咱們要對Creator資源打包規則作更深刻的分析。對於資源打包,咱們主要關注的2點是IO和包體,json的合併能夠減小IO操做,在某些狀況下也可能增大包體。
在Creator構建後每個圖片都會生成一個描述cc.Texture2D的json以及一個cc.SpriteFrame的json,而其中全部的cc.Texture2D.json都會被合併成一個,應該說一個項目在構建以後,正常來講最多隻會有一個cc.Texture2D的json,只是它的data字段會很長。不論圖片是來自不一樣目錄的圖片、圖集、自動圖集、Spine、粒子系統或者BMFont等等,都不影響它們的cc.Texture2D.json被合併。
{ "type": "cc.Texture2D", "data": "0|0|0|0|0|0|0|0|0|0|0|0" }
圖片對應的SpriteFrame又會被怎樣合併呢?默認的狀況下(即不考慮依賴和構建選項的狀況)只有plist圖集和BMFont字體這兩種資源的SpriteFrame會有合併的操做。plist的json會與圖集中全部的SpriteFrame的json合併爲一個json。BMFont字體的fnt對應的json會與SpriteFrame合併爲一個json。
接下來咱們來看一下資源依賴的狀況,使用prefab去引用各類類型的資源,json又會如何合併呢?prefab引用的全部資源中,只有單個圖片和自動圖集中的SpriteFrame會被合併到prefab的json中。
若是咱們在構建時勾選了「內聯全部SpriteFrame」,json又會如何合併呢?除了單個圖片和自動圖集,prefab中用到的圖集的SpriteFrame也會被合併進來,但圖集的合併是拷貝,也就是說原來的圖集和圖集中全部SpriteFrame合併的那個json仍然存在。
若是咱們的資源同時被多個prefab引用,在這種狀況下,是否勾選「內聯全部SpriteFrame」又會有怎樣的區別呢?
前面介紹了prefab的依賴對構建打包的影響,在Creator中,除了prefab能夠去引用資源外,場景也能夠引用外部資源,但正常狀況下場景不會去將其引用的SpriteFrame打包進來。在勾選了「內聯全部SpriteFrame」的狀況下,場景的json纔會去合併引用到的SpriteFrame。
在勾選了「合併初始場景依賴的全部JSON」後,初始場景引用到的全部json都會被合併到初始場景的json文件中,這種合併非拷貝,而是將場景引用到的全部資源的json文件合併到一塊兒(除了SpriteFrame外,還有粒子json、plist圖集完整json、Spine骨骼json、BMFont字體json、動畫json等等)。若是沒有勾選「內聯全部SpriteFrame」,這些json只會放在啓動場景的json中,不會影響包體。值得一提的是圖片的cc.Texture2D這個json,全部被初始場景引用到的紋理會從這個json中剝離,併合併到初始場景。