閒魚Flutter互動引擎系列——整體設計篇
什麼是Candy引擎
Candy引擎是閒魚技術團隊設計開發的一款:
APP嵌入式的、輕量級的、易於開發、效能穩定的互動引擎;
繪製系統高度融合Flutter體系,遊戲場景和Flutter UI支援無縫混排;
動畫系統對主流格式的支援友好且易擴充套件。
本文講解我們為什麼要做這款引擎以及我們是如何設計這款引擎的。
緣起
最近APP遊戲化成為了一個新的風口,把在遊戲中一些好玩的、能吸引使用者的娛樂方式或場景應用在應用當中,以達到增加使用者粘性,提升DAU的效果,成本較低。同時在一些需要對使用者有引導性的場景,遊戲化還可以使使用者更易於接受並完成引導性任務,並透過激勵的形式鼓勵使用者持續沉浸在任務當中,形成良性迴圈。
目前APP內嵌小遊戲一般採用H5小遊戲的方式,而這個方式存在一些隱患,並不被很多應用商店推薦。因此我們需要尋找一種新的安全的方式來實現APP內嵌小遊戲,並且我們希望這個方式開發友好、效能穩定、功能齊全;所以我們遵循這三點去尋找一種新的方式。
思考
我們主要透過下面三種思路來探討APP內嵌小遊戲:
採用Native的遊戲能力
目前Native開發遊戲生態並不是特別成熟,而且採用Native開發,就必須面臨雙端兩套程式碼的問題,開發成本和後續維護成本都會比較高。
採用遊戲引擎,比如Cocos-2dx、Unity等
雖然遊戲引擎目前非常成熟,但是遊戲引擎一般用於開發重度遊戲,所以引擎大小一般比較大,引入遊戲引擎會導致包大小增幅不小。而且遊戲引擎比較複雜,所以引擎啟動耗時較多,比較難做到遊戲頁面秒開;遊戲引擎載入進來後記憶體消耗都會比較大。遊戲引擎和APP間的通訊互動相對較為麻煩,目前沒有比較好的混合棧支援。遊戲引擎的UI能力較弱,無法勝任複雜的APP UI邏輯,若採用遊戲引擎開發內嵌小遊戲,無法融合小遊戲頁面內遊戲場景和Feeds等UI。
採用Flutter的輕量級互動引擎
Flutter本身是基於Skia這個2D繪製引擎實現的跨端APP解決方案,所以它天然具備2D繪製能力,所以採用Flutter來實現App內嵌小遊戲存在可能。目前Flutter存在一些輕量級遊戲引擎,比如Flame,這款引擎支援簡單遊戲邏輯和動畫能力,同時整個遊戲是以一個Widget的形式最終插入到APP中,可以讓小遊戲頁面中游戲部分和UI部分完美融合。
綜上考慮,我們決定採用Flutter的輕量級互動引擎。
Flame?還是自主設計?
Flame引擎目前是Flutter生態中比較不錯的一款小遊戲引擎,但是依然存在很多問題:
遊戲系統不完善:引擎只有Game和Componet,沒有Scene和GameObject概念,這樣會導致遊戲物件巢狀複雜,對多場景不友好。
引擎完全採用Canvas來實現,遊戲場景中無法實現區域性重新整理,存在效能隱患。
缺少GUI系統,場景內巢狀UI比較難。
缺少手勢事件系統。
動畫支援格式不主流:骨骼動畫是透過Flare支援的,不支援DragonBones。粒子動畫最近才上,對主流格式支援也不太友好。
資源管理存在記憶體問題,資源載入後一直不會釋放。
缺少機型適配能力。
基於這些考慮,我們決定重新設計一款Flutter互動引擎:
對標集團的EVA引擎和業界的Unity引擎,完善遊戲系統。
複用Flutter區域性重新整理。
複用Flutter UI作為GUI。
複用Flutter手勢管理。
實現支援主流格式的骨骼動畫和粒子動畫。
複用APP資源庫(圖片庫)。
實現全域性750適配。
其中2-4點本質上是將互動引擎的繪製系統融合入Flutter的繪製體系中,本文下面按解決上面問題的思路依次介紹我們的引擎設計。
Candy引擎設計
框架設計
首先分析遊戲化業務需要哪些能力,分析我們的業務場景,得出遊戲化業務需要圖4-1所示的能力:
圖4-1 遊戲化業務能力需求
拆解後,互動引擎需要有遊戲系統、繪製系統、生命週期系統、GUI系統、物理系統、動畫系統、資源系統、事件系統(手勢管理)。
根據我們之前的定位,互動遊戲繪製融合到Flutter繪製體系中來,基於這個思路,我們可以複用Flutter的UI系統,同時需要融合Flutter和遊戲的手勢管理。最終我們得出如圖4-2所示的框架圖:
圖4-2 互動引擎架構
整個互動引擎架構共分為四部分:
介面層
對外暴露的遊戲介面,主要包含建立遊戲、建立遊戲物件、新增遊戲元件等介面,同時還封裝了一些常用遊戲物件、常用遊戲元件的工廠介面。
遊戲系統
遊戲世界的管理系統,主要管理Game、Scene、GameObject和Compoent間的組織關係,還控制遊戲子系統和繪製系統的啟動與關閉。
遊戲子系統
遊戲化能力補充,主要包含生命週期系統、物理系統、動畫系統和資源系統,被遊戲系統呼叫。
繪製系統
負責遊戲的繪製,本引擎的繪製系統會高度和Flutter繪製邏輯融合,所以相容了GUI系統和事件系統(手勢管理)。
遊戲系統
對標Unity設計,遊戲系統有下列四大元素:
Game:遊戲類,負責整個遊戲的管理,Scene的載入管理以及各子系統管理與排程。
Scene:遊戲場景類,負責遊戲場景中各遊戲物件的管理。
GameObject:遊戲物件類,遊戲世界中游戲物件的最小單位,遊戲世界中的任何物體都是GameObject。
Component:遊戲元件類,表示遊戲物件的能力屬性,比如SpriteComponent表示精靈元件,表示繪製精靈的能力。
GameObject透過組合Component的形式來讓自己擁有各種能力,不同的組合讓GameObject相互之間不一樣。整個遊戲系統的組織關係如圖4-3所示:
圖4-3 遊戲組織形式
生命週期
對標Unity和Flutter特性,我們設計瞭如表4-1所示的生命週期,共有八個回撥,基本可以滿足互動遊戲業務開發。
表4-1 生命週期
渲染系統
基於融合Flutter繪製體系思考,我們就不能全盤用Canvas來做整個遊戲的繪製管理,我們需要將遊戲物件和Flutter的繪製物件RenderObject結合起來,如圖4-4所示:
圖4-4 渲染對映
首先是Game的物件數和Flutter的三顆樹有效融合,所以每一個GameObject必須對應一個Widget、Element和RenderObject。
融合過程主要需要解決以下問題:
遊戲的座標系與Flutter的佈局轉換融合。
動態新增和刪除遊戲物件的處理。
動態修改遊戲繪製深度的處理。
Flutter Inspector對遊戲物件的支援。
整個繪製融合相對複雜,需要解決很多BadCase,後續會另撰文詳述互動引擎繪製融合Flutter繪製體系的過程,本文不再贅述。
GUI系統
由於繪製已經融合到Flutter體系,GameObject都會對應Widget,所以我們可以設計一個特殊的GameObject,支援插入一段Flutter Widget樹,這樣我們就不需要另外實現GUI了,複用Flutter UI作為GUI即可。這個邏輯和繪製融合思路比較一致,將插入的Widget樹作為GUIWidget的孩子即可,在GUIRenderObject中打通layout、paint和hitTest邏輯即可。
這裡給一段我們GUI的示例例項程式碼,開發過程相對簡單:
finalGUIObject gui = IdleFishGame.createGUI('gui', child: GestureDetector( child: Container( width: 100.0, height: 60.0, decoration: BoxDecoration( color: constColor(0xFFA9CCE3), borderRadius: constBorderRadius.all(Radius.circular(10.0),),), child: constCenter( child: Text('Flutter UI示例', style: TextStyle( fontSize: 14.0,),),),), behavior: HitTestBehavior.opaque, onTap: () { print('UI被點選了');},), position: Position(100, 100),);game.scene.addChild(gui);
事件系統
在繪製融合到Flutter體系的基礎上,我們融合了事件系統,增加了手勢處理元件GestureBoxComponent,如圖4-5所示:
圖4-5 手勢競技
整個融合過程分下列幾步:
GestureBoxComponent將開發者註冊手勢回撥方法註冊到手勢識別器中。
GameObject對應的RenderObject複寫hitTest邏輯,按Flutter規範來處理點選的hitTest。透過GestureBoxComponent來判斷點選是否該被消費。
GameObject複寫handEvent來將點選事件傳遞給GestureBoxComponent消費。
GestureBoxComponent收到點選事件後,傳遞給手勢識別器處理。
手勢識別器在將點選傳給手勢競技場開始手勢競技,最終將勝出的手勢返回手勢識別器,最終返回並做出手勢事件響應,當然這一步屬於Flutter邏輯了。
動畫系統
我們目前動畫主要支援骨骼動畫和粒子動畫,骨骼動畫資源目前支援DragonBones,粒子動畫資源目前支援EgretFeather。本文篇幅有限,動畫的具體實現我們後續撰文專門講述。
資源系統
目前互動引擎的資源系統相對簡單,本文就簡單介紹下。資源系統的設計思路是複用APP的資源系統,確保整個APP只有一份資源庫,減少記憶體開銷和增大資源複用率。資源系統架構如圖4-6所示,在遊戲系統和資源系統中間增加了一層代理,相容APP資源系統和兜底資源系統。若我們沒有註冊APP的資源系統,系統會自動呼叫兜底的資源系統。
兜底資源系統目前分兩部分:
兜底圖片庫,複用Flutter的ImageCache,複用Flutter的能力做記憶體管理。
動畫JSON資源管理,目前只實現了JSON讀取邏輯,由於JSON複用性不高,所以目前並沒有實現快取管理。
圖4-6 資源系統
目前資源系統沒有做遠端載入和預載入的能力,這部分在我們的後續規劃中,後續我們再撰文分享具體設計實現。
說在最後
本次主要從全域性上分析介紹了我們正在做的Flutter互動引擎設計,後續我們會透過《閒魚Flutter互動引擎系列》的系列文章分別來詳述一些具體系統的設計,如渲染系統設計、動畫系統等。
本文主要講述了Candy互動引擎的設計,而我們在設計實現過程中遇到了很多問題,如發現了Flutter在繪製過程中存在一定的記憶體洩露,記憶體回收不及時等,我們後續會撰文詳述這些問題的排查與解決,同時還會對Candy引擎的效能與穩定性方面做詳細測試分析,敬請關注。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69900359/viewspace-2670778/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- [閒魚技術] Flutter React程式設計正規化實踐FlutterReact程式設計
- UI2CODE智慧生成Flutter程式碼——整體設計篇UIFlutter
- Flutter系列(三) 整體架構Flutter架構
- 閒魚專家詳解:Flutter React程式設計正規化實踐FlutterReact程式設計
- 閒魚Flutter&FaaS雲端一體化架構Flutter架構
- Flutter高內聚元件怎麼做?閒魚閒魚打造開源高效方案!Flutter元件
- Mac動畫互動設計軟體Mac動畫
- 揭秘!閒魚拉新投放系統如何設計
- Principle for Mac(動畫互動設計軟體)Mac動畫
- Flutter仿閒魚底部導航欄實現Flutter
- GMTC-閒魚Flutter實踐效果訪談Flutter
- Principle for mac(互動原型設計軟體)Mac原型
- Flutter引擎原始碼解讀-記憶體管理篇Flutter原始碼記憶體
- Axure RP 10,互動原型設計軟體原型
- 電商遊戲專題03-互動設計篇遊戲
- [閒魚技術] Release Flutter的最後一公里Flutter
- 閒魚"同款"的Flutter圖片下載功能(demo版)Flutter
- Flutter Worker —— 閒魚這樣實現“邏輯跨平臺”Flutter
- 互動設計法則
- Flutter 引擎啟動流程Flutter
- 閒魚基於Dart生態的FaaS前端一體化建設Dart前端
- 走近科學,探究阿里閒魚團隊透過資料提升Flutter體驗的真相阿里Flutter
- 如何運營設計沉浸式互動體驗模式模式
- MASA Framework - 整體設計思路Framework
- 阿里技術分享:閒魚IM基於Flutter的移動端跨端改造實踐阿里Flutter跨端
- 閒魚又一企業級鉅著《Flutter in action》開放下載Flutter
- 閒魚APP關聯同款寶貝怎麼設定?閒魚關聯同款寶貝的設定方法APP
- 互動設計原則分析
- Flutter之引擎啟動流程Flutter
- 環境互動設計,如何處理掩體的放置?
- 互動多媒體展廳設計都有哪些特點
- 嵌入式軟體架構設計-訊息互動架構
- 閒魚:2023年閒魚日均GMV破10億 超1億人掛出閒置
- Flutter 與Native原生互動Flutter
- Flutter 與 Android 的互動FlutterAndroid
- flutter和Android原生互動FlutterAndroid
- 閒魚基於Flutter技術的架構演進和創新Flutter架構
- Flutter高內聚元件怎麼做?閒魚打造開源高效方案!Flutter元件