程式碼生成器插件與Creator預製體文件解析
- 2020 年 8 月 7 日
- 筆記
前言
-
之前寫過一篇自動生成腳本的工具,但是我給它起名叫半自動程式碼生成器。之所以稱之為半自動,因為我覺得全自動程式碼生成器應該做到兩點:程式碼生成+自動綁定。之前的工具只做了程式碼生成,並沒有做自動綁定,所以鄙人又花時間研究了CocosCreator的預製體文件,實現了自動綁定的能力,並且支援了插件使用方式。
-
本篇內容,不僅僅是宣傳自己的插件工具,還會幫助大家分析一下Creator的預製體文件格式,使購買插件的同學可以將插件價值最大化,也能讓讀者對Creator的預製體文件有所了解。
Creator 預製體文件格式分析
- 首先我們展示一小段預製體文件。
[
{
"__type__": "cc.Prefab",
"_name": "",
"_objFlags": 0,
"_native": "",
"data": {
"__id__": 1
},
"optimizationPolicy": 0,
"asyncLoadAssets": false,
"readonly": false
},
{
"__type__": "cc.Node",
"_name": "LoginView",
"_objFlags": 0,
"_parent": null,
"_children": [
{
"__id__": 2
},
{
"__id__": 6
},
{
"__id__": 18
},
{
"__id__": 21
},
{
"__id__": 33
},
{
"__id__": 42
},
{
"__id__": 63
},
{
"__id__": 84
}
],
"_active": true,
"_components": [
{
"__id__": 105
},
{
"__id__": 106
}
],
"_prefab": {
"__id__": 107
},
"_opacity": 255,
"_color": {
"__type__": "cc.Color",
"r": 255,
"g": 255,
"b": 255,
"a": 255
},
"_contentSize": {
"__type__": "cc.Size",
"width": 960,
"height": 640
},
"_anchorPoint": {
"__type__": "cc.Vec2",
"x": 0.5,
"y": 0.5
},
"_trs": {
"__type__": "TypedArray",
"ctor": "Float64Array",
"array": [
480,
320,
0,
0,
0,
0,
1,
1,
1,
1
]
},
"_eulerAngles": {
"__type__": "cc.Vec3",
"x": 0,
"y": 0,
"z": 0
},
"_skewX": 0,
"_skewY": 0,
"_is3DNode": false,
"_groupIndex": 0,
"groupIndex": 0,
"_id": ""
}
]
-
當你第一次看到這個文件的時候可能會有所疑惑,此文件是一個一維數組的json對象。
數組第一個位置是預製體文件的描述可以忽略。第二個位置的對象就是這個文件根節點對應的屬性了。也是最重要的部分。從數據的_children 和_components欄位可以看出,引擎是根據__id__這個欄位來尋找其他數據的。只不過這個__id__並非你所理解的id,而是數組的索引位置。並且配置中所有涉及到尋找其他數據都是用的這種__id__方式。包括給自己的腳本組件綁定節點。 -
由於我們是要導出和綁定其中的屬性,所以我們只關注__type__,_name,_childern,_components這幾個屬性就可以了。
-
__type__: 是一個比較重要的屬性,對於普通的組件,類型會是cc.Node,cc.Sprite,cc.Button之類的。對於腳本的類型比較特別,它並不是你定義的類名,而已一串經過處理的字元。但是它的特點就是長。所以我會用長度是否大於20來判斷是否是腳本組件。
下方是我已經做好綁定腳本的配置內容。也說明如果你要給預製體添加腳本也就是給預製體的數組添加一個下面格式的配置而已。通過下方的配置也可以看出我給這個腳本綁定了start$VButton,login$VLabel,login$\VLabel,show$VRichText四個變數和testItem$ATestItemView一個數組。
{
"__type__": "3e347nRcdVAiYpq6icd+8+w",
"_name": "",
"_objFlags": 0,
"node": {
"__id__": 1
},
"_enabled": true,
"start$VButton": {
"__id__": 14
},
"login$VLabel": {
"__id__": 19
},
"back$VButton": {
"__id__": 29
},
"show$VRichText": {
"__id__": 40
},
//綁定的是一個數組,長度為3
"testItem$ATestItemView": [
{
"__id__": 61
},
{
"__id__": 82
},
{
"__id__": 103
}
],
"_id": ""
},
- _name: 它是所有節點的名稱,注意,組件是沒有名稱的,所以我們處理文件的時候也是從根節點深度遍歷所有的子節點,然後在遍歷節點的時候出理它的組件。
因為Creator的節點都是有名稱的,而且還有空格,支援重名,這些都是程式碼生成器所不允許的。所以如果你想導出一個屬性就要用特定的字元標識。
比如工具現在使用的是$V標識輸出的是一個變數。$A標識輸出的是一個數組,當然數組還需要名稱都相同。
var TAG = ‘$V’
var LIST = ‘$A’
當然這裡邊還有一個問題就是一個節點可能掛了很多組件,那我們要怎麼出理呢?
首先是做一個篩選,只有給定的組件才可以輸出
var NORMAL_COMP_LIST = [‘cc.Label’, ‘cc.Sprite’, ‘cc.RichText’, ‘cc.Button’, ‘cc.ScrollView’]
其次工具會將名稱後邊加上類型,以區別不同的組件的情況。
因此這也是一個可自定義和擴展的部分。
-
_children: 就是遍歷的節點,我們不用關心這個配置文件的數組有多長,就從這些子節點深度遍歷就可以了。
-
_components: 遍歷每個節點的時候我們再遍歷一次它的所有組件,然後做上邊我們說的操作。這樣一個文件走一遍之後我們的類需要的資訊也就生成了。
問題討論
-
既然腳本的類型是 “type“: “3e347nRcdVAiYpq6icd+8+w”,那麼我們怎麼找到對應的腳本文件的名稱呢?
當你右鍵一個腳本文件,點擊打開Library中的資源選項,會跳轉到一個js文件中
這個文件有四個特點,一是它的文件名是你腳本的uuid.js。二是文件帶有cc._RF.push(module,,三是帶有類型”3e347nRcdVAiYpq6icd+8+w”。四是帶有腳本名稱。所以你只要查找文件中帶有cc._RF.push(module,欄位並且帶有你傳入的類型的文件並返回後處理一下就可以獲得腳本名稱了。當然也可以得到路徑並做好import from 的設置。
這裡可能有人會覺得,搜索整個imports路徑是不是很慢,其實不是,即使再慢還能比手動綁定慢嗎?所以這個速度可以無視。 -
怎麼處理的creator自帶的meta機制,我是將程式碼生成和自動綁定分成兩個腳本。程式碼生成之後會刷新生成腳本的目錄,然後再調用自動綁定的腳本。刷新預製體目錄。
這裡邊一直強調的就是刷新指定的目錄,而不是刷新整個assets或者整個Script。原因是我在使用的時候發現,刷新整個目錄會造成編輯器卡死,體驗很不好,所以當你不設置的腳本目錄不存在就做導出時,creator顯示的目錄位置不是實際中硬碟中顯示的位置,重啟編輯器後才會正確,就是因為我刷新的目錄是你指定的目錄。如果指定的目錄不存在,目錄會創建,但是不會刷新。
刷新後的預製體文件可能會報錯,可以無視,雙擊預製體文件重新查看就可以了。 -
如何做到綁定嵌套的預製體的節點?
首先在導出程式碼的時候一旦遇到有腳本的節點就返回。繼續遍歷其他子節點。這樣你的腳本里就不會聲明其他腳本要聲明的內容。
然後在綁定的時候首先會找到應該做數據綁定的腳本,然後再深入遍歷,當你發現你處理的這個節點上有腳本的時候就會用它身上腳本處理它的子節點。所以如果一個節點有多個腳本就只能綁定第一個腳本的數據。
功能介紹
-
根據預製體文件生成腳本
-
自定義輸入目錄和輸出目錄
-
自動綁定屬性+數組
使用$V標識變數
使用$A標識數組
屬性名稱默認帶有類型。
-
自動綁定button事件
-
可擴展導出屬性類型
-
自動綁定其他預製體的屬性,和button事件
-
自動導入使用到的其他腳本
手懶不想自己實現的可以關注公眾號,進入微店購買。
歡迎掃碼關注公眾號《微笑遊戲》,瀏覽更多內容。
歡迎掃碼關注公眾號《微笑遊戲》,瀏覽更多內容。