寫於 2018.11.01
在近期使用CocosCreator(以下簡稱CC)開發HTML5遊戲的工作中,發現公司許多遊戲都有著相同的元素,比如倒數計時條、結算頁面等等。在早期的開發中,我們並沒有摸索到複用的辦法,只能在不同的遊戲專案中從頭開始寫。隨著需求越來越多,重複造輪子肯定不是一個好辦法,那麼對於CC專案來說,能不能把這些可複用的遊戲元素作為元件封裝抽離出來呢?經過一番探索,終於找到了解決的辦法。
什麼是CC元件
以我們在手Q上的“太鼓達人”小遊戲為例子,它的倒數計時條和結算頁面,在其他的小遊戲裡面也是存在的,僅僅是外觀上有所不同,但當中的邏輯處理是一致的。這裡的倒數計時條和結算頁面,都可以理解為元件。
兩個元件的邏輯如下:
-
倒數計時條可以設定遊戲時間,在遊戲時間內其填充長度不斷縮減;倒數計時條右側會顯示所剩時間;在倒數計時結束後會執行回撥動作。
-
結算頁面可以設定等級分值,達到或超過具體的等級分值可以獲得星星;星星會按照動畫邏輯展示;下方會從0開始對分數進行結算;結算完成後會執行回撥動作。
通過這個例子不難理解,一個所謂的CC元件,就是一個包含了邏輯、圖片、動畫、音訊等不同資源的遊戲節點。在CC裡面,一個節點它長這個樣子:
可以看到,編輯器左側定義了它的結構,中間是它的具體體現,右側是它的相關屬性。
如果我想在其他的專案中複用這個已經定義好的節點,應該怎麼做呢?
轉化成預製資源
在CC裡面,預製資源是非常重要部分,可以把它理解為節點的模板。如果要將一個已經做好的節點抽象成元件,把它變成預製資源會是一個最合適的辦法。
當我們在CC編輯器定義好一個節點,給它關聯邏輯指令碼、靜態資源以後,直接把它從編輯器的層級管理器
拖到資源管理器
就可以把它轉化為預製資源。但是由於CC內資源的關聯是基於資源路徑的,所以在抽象一個CC元件出來之前,我們有必要把該元件所有用到的資源都放在一起,以方便以後的複用,否則很可能在其他工程複用的時候會報找不到資源的錯誤。
新建一個CC工程,清空assets/
目錄,然後在裡面建立Components/
目錄,作為我們存放CC元件的目錄。以遊戲結果頁Result
為例,按照如下目錄結構進行初始化,放入必要的資源:
.
├── Resources # 元件靜態資源
│ ├── score.png
│ └── star.png
└── Result.ts # 元件指令碼
複製程式碼
然後在CC編輯器中,通過拖拽的方式給子節點新增圖片,最後綁上邏輯指令碼Result.ts
:
完成以後,把它拖到資源管理器的assets/Components/Result
目錄下成為一個預製資源。
為了讓其他使用者能夠方便地使用這個元件,所以可以為其新增一個demo,裡面放置著僅有這個元件的場景和場景所需的指令碼。當使用者需要了解這個元件時,只需要預覽Demo場景即可,而元件的一些方法也可以在Demo指令碼中看到。最終目錄結構如下:
.
├── Demo # 元件使用Demo
│ ├── Result.fire
│ └── ResultDemo.ts
├── Resources # 元件靜態資源
│ ├── score.png
│ └── star.png
├── Result.prefab # 元件節點
└── Result.ts # 元件指令碼
複製程式碼
如何使用
簡單來說,只要把元件庫工程的Components/
目錄整個複製到目標工程的assets/
目錄下,然後把預製資源節點拖到層級管理器去就可以了。當然這樣的手動操作不夠優雅,所以我們可以藉助shell指令碼來幫我們簡化這個步驟。
在目標工程的根目錄下新建一個download.sh
指令碼,寫入如下內容:
#!/bin/bash
# 先清理一下
echo "Clearing workbench..."
rm -rf ./cocos-components
rm -rf ./assets/Components
# 直接clone元件庫工程,取出Components目錄,然後刪掉元件庫工程
echo "Cloning project..."
git clone http://git.xxx.com/cocos-components.git
cp -r ./cocos-components/assets/Components ./assets
rm -rf ./cocos-components
echo "Done!"
複製程式碼
以後只需要執行./download.sh
就可以下載到最新的元件庫了,非常方便。
元件設計規範
元件的設計應該遵循“黑盒子”原則,它不依賴於其他元件,也不影響其他元件。元件的狀態由元件自身儲存,如果需要改變元件的狀態或行為,應該通過它向外暴露可配置項或介面(通過Cocos Creator的屬性檢查器修改或者引入元件的指令碼例項)。
以Progress
元件為例。
它向外提供了gameDuration
配置項,定義倒數計時的時長。另外它也提供了一個setTimeoutCallback()
的方法,用於定義當倒數計時結束後的行為。前者可以直接在Cocos Creator的屬性檢查器裡面修改,後者則需要在遊戲指令碼中通過程式碼的方式去使用:
import Progress from '../Components/Progress/Progress'
@ccclass
export default class Game extends cc.Component {
start () {
Progress.instance.setTimeoutCallback(() => {
console.log('Test progress timeout callback!')
})
}
}
複製程式碼
在定義元件的指令碼的時候,要注意為該指令碼新增一個名為instance
的靜態屬性,以供指令碼之間的呼叫:
export default class Progress extends cc.Component {
static instance = null
constructor () {
super()
Progress.instance = this
}
}
複製程式碼
此外,搭建元件庫必須注意命名規範,這樣不管是開發方還是呼叫方,都可以省去不少的煩惱。
後續優化
CC元件庫工程也是一個完整的CC遊戲,我們可以在這個遊戲裡面新增元件選單,點選選單就可以載入對應元件的場景,實時預覽元件的效果。這個想法也會在之後付諸實踐,爭取早日開源出來。