1. 程式人生 > >CocosCreator元件化程式設計的探索

CocosCreator元件化程式設計的探索

使用CocosCreator已經一年了,在此期間一直在摸索,如何才是元件化程式設計的最優實踐。Shawn屬於半野生的路子,水平不高,但不時會陷入一些問題瞎琢磨。我根據自己的經驗,總結了一套元件化程式設計模型:法寶結界模型。

但在介紹法寶結界元件模型之前,先回顧一下控制元件和元件的概念。

一、控制元件與元件

在Cocos2d-x/lua/js的年代,UI元素都以控制元件類的形式存在。只有cc.Node的子類才能在介面上顯示,例如:cc.Image、cc.Button、cc.Text。我們編寫的介面程式碼也屬於cc.Node的子類或系統控制元件的子類。

在Creator中我們自己編寫的cc.Component的子類指令碼,能稱之為控制元件嗎?

image

1.我所理解的控制元件

我覺得要能稱的上控制元件,必須是能夠被介面編輯器程式碼所控制,並能相對獨立完成一項或多項任務的程式模組。而且控制元件具有一定範圍的通用性,可以獨立執行,可以被獨立測試。

我們要自定控制元件,一類是cc.Componet子類指令碼 + 預製體的結合;第二類是純cc.Componet的子類指令碼(不含預製體),也可以是系統元件的派生類。不含預製體的指令碼其實是引擎自動幫我們生成的,當拖入一個元件指令碼到場景編輯器,Creator會自動生成一個節點,並將指令碼掛載到這個節點上。

這兩類控制元件有什麼不同呢?

指令碼+預製體:控制的是預製體中的節點和子節點,以及節點上的控制元件。

純指令碼: 只能控制當前節點,也可以控制當前節點上的其它元件。

可以看出,這兩類元件程式碼在他們控制的範圍上是不同的。

2. 元件的悲劇

cc.Componet的子類都是元件,但他們要想要上升成為控制元件卻很難。因為大多元件程式碼,都無法像系統控制元件那樣獨立完成一專案任務,其原因之一是濫用元件的properties視覺化編輯功能,將本職範圍內的節點做為成員變數,目的僅僅是為了方便訪問。

[圖片上傳失敗…(image-346e88-1518414298577)]

從Creator範例工程中的TestList首場景為例,Menu.js元件指令碼掛載到Menu節點上,最後一個Menu.testList屬性設定是非當前節點的子節點,控制權延生到了外面去了。前面幾個屬性(Text, Readme…)都是通過編輯器拖拽將Menu節點下的幾個子節點配置到了元件指令碼上,他們對於Menu.js應該屬於私有成員變數,也變成了公開的了。

通過簡單拖拽配置成員屬性確實讓程式開發變的簡單,但如果濫用會有一個嚴重的問題:控制元件屬性由原來的點狀(控制自身節點)或線性(控制子節點或成員節點)關係,變成了網狀關係(控制自身以外的節點)。

這將導致元件指令碼難以獨立完成任務和測試,必須通過編輯器正確配置才能工作,就像在一個模組程式碼中訪問了全域性變數一樣。要讓Menu.js成為控制元件的辦法,最好是將TestList節點放到Menu節點內部。把Menu節點拖到資源管理器中成為一個prefab。

image

不知道如何下手,設定這些屬性

不知道大家有沒有遇到過,在屬性檢查器上密密麻麻的屬性配置,不知道該如何下手?更讓人頭痛的是,不小心程式碼衝突,導致元件屬性配置丟了,再看程式碼,指令碼中的屬性變數與節點名字又對應不上,就連編寫這個模組程式碼的人都搞不懂是怎麼會事!

網狀關係的程式組織結構,會導至模組之間相互依賴,可重用性極低。如何規範元件的編寫方式,確保模組的內聚性值得我們多多思考。

二、法寶與結界

下面來聊聊我總結的法寶結界模型,假想一個完整的世界,為了維護這個世界的有序執行,設定了一個結界。結界中有無數的法寶參與到世界的執行之中,貢獻出力量。

1.法寶型元件

法寶型元件:以裝飾宿主節點為己任,從不控制其它節點。

法寶型的特點是通用性強,可掛載任意節點執行,Creator內建的元件絕大多數屬於這類。例如有Sprite、Label、Button、Widget等,可以看出純指令碼的元件就屬於法寶型。

2.結界型元件

結界型元件:管理和控制其它節點及節點上的元件,通常會根據上層業務要求,呼叫其它節點的屬性方法完成任務。

結界型的特點是業務邏輯性強,通用性差,通常是對法寶型元件的指揮和管理。元件+prefab就屬於這類,由於結界型元件大多是定製的,它並且不能隨便掛載到別的節點上(更多的是隻能掛載到唯一的節點上)。

3. 結界的祕密

話說天有九重,九隻是個虛數,其實是很多的意思。一個結界型元件,對於它的上層結界來說,他又是一個法寶型元件,這就形成了模組化。

image

比如有一個名為A的prefab,將元件指令碼A.js掛載到prefab的根結點。當另一個場景或預製體中例項化這個A.prefab時,A.js就上升為一個控制元件,他管理了A.prefab下的所有節點,但對於當前場景來說,它又體現為一個法寶型元件,而成為了一個控制元件。

對內是結界,從根節點開始自下而下管理所有子節點;對外是法寶,從根節點獲取法寶暴露的屬性方法。這樣以內部線性、總體樹狀的程式結構,是不是要比網狀的結構更好些呢?

三、小結

uikiller庫是我在元件化程式設計上的一點成果,可以方便管理prefab下的任意節點和元件,以及節點上的觸控事件。奉上一段uikill的使用視訊 ,結束這篇分享。
在這裡插入圖片描述
雷神歸來-Thor元件實戰演示

歡迎關注「奎特爾星球」微信公眾號,來我們一起成長!