臥槽!骨瘦如柴陳皮皮又出新插件了,還免費(fèi)開源!
前言
嗐,不知道你有沒(méi)有過(guò)這樣的煩惱。
當(dāng)你想要確定一個(gè)資源被哪些節(jié)點(diǎn)引用的時(shí)候,使用資源管理器的查找引用卻只能精確到預(yù)制體或場(chǎng)景。
對(duì)于預(yù)制體還好說(shuō),里面的節(jié)點(diǎn)一般不會(huì)很多,找起來(lái)還是比較快的。
但是場(chǎng)景里面的節(jié)點(diǎn)這么多,節(jié)點(diǎn)還可能是關(guān)閉著的,那找起來(lái)可太麻煩了。
那咋辦嘛?
于是我又寫了個(gè)編輯器擴(kuò)展。
是的,這篇文章就給大家介紹一下我的新擴(kuò)展:引用查找器。
正文
? 本文主要包含兩部分:
擴(kuò)展介紹 原理解析
讓我們開始吧!
引用查找器
簡(jiǎn)介
這個(gè)擴(kuò)展的用處很簡(jiǎn)單,就是讓你可以一鍵快速查找資源的所有引用,對(duì)于預(yù)制體或場(chǎng)景的引用還可以精確到節(jié)點(diǎn)上的組件和屬性。
注意:本插件無(wú)法查找腳本代碼中的動(dòng)態(tài)引用(動(dòng)態(tài)加載資源)。
開源
本擴(kuò)展項(xiàng)目完全開源,倉(cāng)庫(kù)地址:https://gitee.com/ifaswind/ccc-references-finder
如果你覺得這個(gè)項(xiàng)目還不錯(cuò),請(qǐng)不要忘記點(diǎn)個(gè) ?Star!
截圖




下載
本擴(kuò)展已上架擴(kuò)展商店,點(diǎn)擊 Cocos Creator 編輯器頂部菜單欄中的 [擴(kuò)展] -> [擴(kuò)展商店] 即可打開擴(kuò)展商店。
在商店頁(yè)面上方的搜索框中輸入“引用查找器”并搜索就可以找到本擴(kuò)展,點(diǎn)進(jìn)去直接安裝即可(建議安裝到全局)。

或者
到碼云倉(cāng)庫(kù)里自行下載安裝~
使用說(shuō)明
安裝擴(kuò)展后,點(diǎn)擊 Cocos Creator 編輯器頂部菜單欄中的 [擴(kuò)展] -> [引用查找器] -> [設(shè)置] 即可打開擴(kuò)展的設(shè)置面板。
有以下 3 個(gè)選項(xiàng):
自動(dòng)展開查找結(jié)果:切換不同的結(jié)果展示方式(自動(dòng)展開或手動(dòng)展開) 結(jié)果精確到節(jié)點(diǎn):結(jié)果精確到預(yù)制體或場(chǎng)景中的節(jié)點(diǎn)上的組件和屬性(有的話) 查找快捷鍵:在資源管理器中選擇資源后按下快捷鍵即可查找資源的引用(默認(rèn)為 F6)
原理解析
雖然項(xiàng)目已經(jīng)開源,源碼隨便看隨便改,不過(guò)還是在這里給大家稍微解釋下擴(kuò)展的工作原理吧~
查找場(chǎng)景和預(yù)制體中的引用
? 預(yù)制體的數(shù)據(jù)結(jié)構(gòu)和場(chǎng)景大致相同,這里只拿場(chǎng)景舉例。
沒(méi)有專門研究過(guò)場(chǎng)景文件數(shù)據(jù)結(jié)構(gòu)的小伙伴,可能會(huì)覺得里面的數(shù)據(jù)應(yīng)該是樹形結(jié)構(gòu),就像層級(jí)管理器中展示出來(lái)的那樣,節(jié)點(diǎn)與子節(jié)點(diǎn)一層一層地嵌套著。
實(shí)則不然,場(chǎng)景文件的數(shù)據(jù)其實(shí)是扁平結(jié)構(gòu)的。不理解?那聽我娓娓道來(lái)~
? 扁平化
樹形結(jié)構(gòu)就好像一個(gè)多維數(shù)組,不同緯度間不斷嵌套,像這樣:
[0, 1, [2, 3, 4], 5, [6, [7, 8]], 9]當(dāng)我們調(diào)用數(shù)組的
flat()函數(shù)將這個(gè)多維數(shù)組扁平化,數(shù)組就會(huì)變成:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]這就是降維打擊!
? 舉個(gè)栗子
以新建項(xiàng)目的 helloworld 場(chǎng)景為例,其節(jié)點(diǎn)層級(jí)是這樣的:

而 helloworld.fire 的文件內(nèi)容是這樣的(為了更直觀地展示數(shù)據(jù)結(jié)構(gòu)我去除了文件中大部分不相關(guān)內(nèi)容):

我們可以發(fā)現(xiàn),在場(chǎng)景中所有節(jié)點(diǎn)和組件都是一個(gè)個(gè)獨(dú)立的對(duì)象,且這些對(duì)象都處于同一個(gè)一維數(shù)組中。
每個(gè)節(jié)點(diǎn)對(duì)象中都儲(chǔ)存了該節(jié)點(diǎn)的父節(jié)點(diǎn) id,子節(jié)點(diǎn) id 和身上的組件 id 等信息。 每個(gè)組件對(duì)象中都儲(chǔ)存了該組件所屬的節(jié)點(diǎn) id 和組件的一些數(shù)據(jù)。
而這些 id(__id__)其實(shí)就是對(duì)象在數(shù)組中的下標(biāo)。
比如 background 節(jié)點(diǎn)的父節(jié)點(diǎn) id 為 2,那么就是數(shù)組中的第 3 個(gè)對(duì)象,即 _name 為 Canvas 的節(jié)點(diǎn)對(duì)象;又如 Main Camera 節(jié)點(diǎn)上有一個(gè)組件的 id 為 4,那就是數(shù)組中的第 4 個(gè)對(duì)象:cc.Camera 對(duì)象。
生成節(jié)點(diǎn)樹
想要判斷場(chǎng)景是否引用了某個(gè)資源,只需要檢查場(chǎng)景的數(shù)據(jù)中是否包含資源的 uuid 即可。
但是,如果想要獲取具體引用的節(jié)點(diǎn)和組件,而扁平化的數(shù)據(jù)結(jié)構(gòu)是非常不利于查找的。
所以在正式開始查找之前,先將場(chǎng)景的數(shù)據(jù)轉(zhuǎn)為樹形結(jié)構(gòu)(節(jié)點(diǎn)樹),且只留下節(jié)點(diǎn)和組件對(duì)象中一些有用的屬性,如 _name、__type__ 和 __uuid__,還要將節(jié)點(diǎn)的完整路徑保存起來(lái)。
? 具體生成節(jié)點(diǎn)樹的代碼在這里(代碼太長(zhǎng),就不貼了):
傳送門:https://gitee.com/ifaswind/ccc-references-finder/blob/v1.1.0/main.js#L362
? 轉(zhuǎn)換后的場(chǎng)景數(shù)據(jù)結(jié)構(gòu)就像這樣:

至此,我們就擁有了場(chǎng)景的節(jié)點(diǎn)樹,查找引用的任務(wù)已經(jīng)變得無(wú)比簡(jiǎn)單,只需在節(jié)點(diǎn)樹中查詢目標(biāo) uuid 即可獲取場(chǎng)景中的所有引用(包括節(jié)點(diǎn)路徑、組件和屬性信息)。
? 而判斷對(duì)象中是否包含 uuid 則是用簡(jiǎn)單的遞歸實(shí)現(xiàn)的:
containsValue(object,?value)?{
????let?result?=?false;
????const?search?=?(_object)?=>?{
????????if?(Object.prototype.toString.call(_object)?===?'[object?Object]')?{
????????????for?(const?key?in?_object)?{
????????????????if?(_object[key]?===?value)?{
????????????????????result?=?true;
????????????????????return;
????????????????}
????????????????search(_object[key]);
????????????}
????????}?else?if?(Array.isArray(_object))?{
????????????for?(let?i?=?0;?i?????????????????search(_object[i]);
????????????}
????????}
????}
????search(object);
????return?result;
}
加點(diǎn)魔法
為了加快查詢速度,每個(gè)場(chǎng)景和預(yù)制體的節(jié)點(diǎn)樹都只會(huì)生成一次,所以只有第一次查找會(huì)稍微慢一點(diǎn)點(diǎn)(其實(shí)也很快)。
另外擴(kuò)展內(nèi)部監(jiān)聽了項(xiàng)目中場(chǎng)景和預(yù)制體的修改,以便及時(shí)更新對(duì)應(yīng)的節(jié)點(diǎn)樹。
//?監(jiān)聽資源更新事件
'asset-db:asset-changed'(event,?info)?{
????//?只處理場(chǎng)景和預(yù)制體
????if?(info.type?===?'scene'?||?info.type?===?'prefab')?{
????????//?獲取資源的路徑
????????const?path?=?Editor.assetdb.uuidToFspath(info.uuid);
????????//?更新節(jié)點(diǎn)樹
????????this.updateNodeTree(path);
????}
}
查找其它資源中的引用
對(duì)于動(dòng)畫片段、材質(zhì)和字體等資源,只需簡(jiǎn)單判斷資源數(shù)據(jù)中是否包含目標(biāo) uuid 即可。
? 就像這樣:
//?動(dòng)畫片段資源(擴(kuò)展名為?.anim)
if?(extname?===?'.anim')?{
????const?data?=?JSON.parse(Fs.readFileSync(filePath));
????//?截取有效數(shù)據(jù)
????const?curveData?=?data['curveData'];
????//?數(shù)據(jù)中是否包含目標(biāo)?uuid
????const?contains?=?ObjectUtil.containsValue(curveData,?uuid);
????if?(contains)?{
????????//?獲取文件路徑
????????const?fileUrl?=?Editor.assetdb.fspathToUrl(filePath);
????????//?保存結(jié)果
????????results.push({?type:?typeMap[extname],?fileUrl:?fileUrl?});
????}
}菜鳥小棧
?我是陳皮皮,一個(gè)還在不斷學(xué)習(xí)(如何脫單)的游戲開發(fā)者
一個(gè)熱愛分享的 Cocos Star Writer。
?這是我的個(gè)人公眾號(hào),專注但不僅限于游戲開發(fā)和前端技術(shù)分享。
?每一篇原創(chuàng)都非常用心,你的關(guān)注就是我原創(chuàng)的動(dòng)力!
