臥槽!骨瘦如柴陳皮皮又出新插件了,還免費(fèi)開源!
前言
嗐,不知道你有沒有過這樣的煩惱。
當(dāng)你想要確定一個(gè)資源被哪些節(jié)點(diǎn)引用的時(shí)候,使用資源管理器的查找引用卻只能精確到預(yù)制體或場景。
對于預(yù)制體還好說,里面的節(jié)點(diǎn)一般不會(huì)很多,找起來還是比較快的。
但是場景里面的節(jié)點(diǎn)這么多,節(jié)點(diǎn)還可能是關(guān)閉著的,那找起來可太麻煩了。
那咋辦嘛?
于是我又寫了個(gè)編輯器擴(kuò)展。
是的,這篇文章就給大家介紹一下我的新擴(kuò)展:引用查找器。
正文
? 本文主要包含兩部分:
- 擴(kuò)展介紹
- 原理解析
讓我們開始吧!
引用查找器
簡介
這個(gè)擴(kuò)展的用處很簡單,就是讓你可以一鍵快速查找資源的所有引用,對于預(yù)制體或場景的引用還可以精確到節(jié)點(diǎn)上的組件和屬性。
注意:本插件無法查找腳本代碼中的動(dòng)態(tài)引用(動(dòng)態(tài)加載資源)。
開源
本擴(kuò)展項(xiàng)目完全開源,倉庫地址:https://gitee.com/ifaswind/ccc-references-finder
如果你覺得這個(gè)項(xiàng)目還不錯(cuò),請不要忘記點(diǎn)個(gè) ?Star!
截圖
截圖 1
截圖 2
查找面板
設(shè)置面板下載
本擴(kuò)展已上架擴(kuò)展商店,點(diǎn)擊 Cocos Creator 編輯器頂部菜單欄中的 [擴(kuò)展] -> [擴(kuò)展商店] 即可打開擴(kuò)展商店。
在商店頁面上方的搜索框中輸入“引用查找器”并搜索就可以找到本擴(kuò)展,點(diǎn)進(jìn)去直接安裝即可(建議安裝到全局)。

或者
到碼云倉庫里自行下載安裝~
使用說明
安裝擴(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ù)制體或場景中的節(jié)點(diǎn)上的組件和屬性(有的話)
- 查找快捷鍵:在資源管理器中選擇資源后按下快捷鍵即可查找資源的引用(默認(rèn)為 F6)
原理解析
雖然項(xiàng)目已經(jīng)開源,源碼隨便看隨便改,不過還是在這里給大家稍微解釋下擴(kuò)展的工作原理吧~
查找場景和預(yù)制體中的引用
? 預(yù)制體的數(shù)據(jù)結(jié)構(gòu)和場景大致相同,這里只拿場景舉例。
沒有專門研究過場景文件數(shù)據(jù)結(jié)構(gòu)的小伙伴,可能會(huì)覺得里面的數(shù)據(jù)應(yīng)該是樹形結(jié)構(gòu),就像層級管理器中展示出來的那樣,節(jié)點(diǎn)與子節(jié)點(diǎn)一層一層地嵌套著。
實(shí)則不然,場景文件的數(shù)據(jù)其實(shí)是扁平結(jié)構(gòu)的。不理解?那聽我娓娓道來~
? 扁平化
樹形結(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 場景為例,其節(jié)點(diǎn)層級是這樣的:
場景的層級管理器而 helloworld.fire 的文件內(nèi)容是這樣的(為了更直觀地展示數(shù)據(jù)結(jié)構(gòu)我去除了文件中大部分不相關(guān)內(nèi)容):
場景的數(shù)據(jù)結(jié)構(gòu)我們可以發(fā)現(xiàn),在場景中所有節(jié)點(diǎn)和組件都是一個(gè)個(gè)獨(dú)立的對象,且這些對象都處于同一個(gè)一維數(shù)組中。
- 每個(gè)節(jié)點(diǎn)對象中都儲(chǔ)存了該節(jié)點(diǎn)的父節(jié)點(diǎn) id,子節(jié)點(diǎn) id 和身上的組件 id 等信息。
- 每個(gè)組件對象中都儲(chǔ)存了該組件所屬的節(jié)點(diǎn) id 和組件的一些數(shù)據(jù)。
而這些 id(__id__)其實(shí)就是對象在數(shù)組中的下標(biāo)。
比如 background 節(jié)點(diǎn)的父節(jié)點(diǎn) id 為 2,那么就是數(shù)組中的第 3 個(gè)對象,即 _name 為 Canvas 的節(jié)點(diǎn)對象;又如 Main Camera 節(jié)點(diǎn)上有一個(gè)組件的 id 為 4,那就是數(shù)組中的第 4 個(gè)對象:cc.Camera 對象。
生成節(jié)點(diǎn)樹
想要判斷場景是否引用了某個(gè)資源,只需要檢查場景的數(shù)據(jù)中是否包含資源的 uuid 即可。
但是,如果想要獲取具體引用的節(jié)點(diǎn)和組件,而扁平化的數(shù)據(jù)結(jié)構(gòu)是非常不利于查找的。
所以在正式開始查找之前,先將場景的數(shù)據(jù)轉(zhuǎn)為樹形結(jié)構(gòu)(節(jié)點(diǎn)樹),且只留下節(jié)點(diǎn)和組件對象中一些有用的屬性,如 _name、__type__ 和 __uuid__,還要將節(jié)點(diǎn)的完整路徑保存起來。
? 具體生成節(jié)點(diǎn)樹的代碼在這里(代碼太長,就不貼了):
傳送門:https://gitee.com/ifaswind/ccc-references-finder/blob/v1.1.0/main.js#L362
? 轉(zhuǎn)換后的場景數(shù)據(jù)結(jié)構(gòu)就像這樣:
轉(zhuǎn)換后的節(jié)點(diǎn)樹至此,我們就擁有了場景的節(jié)點(diǎn)樹,查找引用的任務(wù)已經(jīng)變得無比簡單,只需在節(jié)點(diǎn)樹中查詢目標(biāo) uuid 即可獲取場景中的所有引用(包括節(jié)點(diǎn)路徑、組件和屬性信息)。
? 而判斷對象中是否包含 uuid 則是用簡單的遞歸實(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è)場景和預(yù)制體的節(jié)點(diǎn)樹都只會(huì)生成一次,所以只有第一次查找會(huì)稍微慢一點(diǎn)點(diǎn)(其實(shí)也很快)。
另外擴(kuò)展內(nèi)部監(jiān)聽了項(xiàng)目中場景和預(yù)制體的修改,以便及時(shí)更新對應(yīng)的節(jié)點(diǎn)樹。
//?監(jiān)聽資源更新事件
'asset-db:asset-changed'(event,?info)?{
????//?只處理場景和預(yù)制體
????if?(info.type?===?'scene'?||?info.type?===?'prefab')?{
????????//?獲取資源的路徑
????????const?path?=?Editor.assetdb.uuidToFspath(info.uuid);
????????//?更新節(jié)點(diǎn)樹
????????this.updateNodeTree(path);
????}
}
查找其它資源中的引用
對于動(dòng)畫片段、材質(zhì)和字體等資源,只需簡單判斷資源數(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è)人公眾號,專注但不僅限于游戲開發(fā)和前端技術(shù)分享。
?每一篇原創(chuàng)都非常用心,你的關(guān)注就是我原創(chuàng)的動(dòng)力!
