Categories
程式開發

如何用WebAssembly將桌面遊戲編輯器移植到瀏覽器上


本文要點

  • 儘管WebAssemly還在積極開發當中,並且仍然比較小眾,但這項技術本身已經足夠成熟,足以用來將諸如桌面平台遊戲編輯器之類的複雜應用程序移植到Web上。
  • 將桌面平台軟件移植到WebAssembly的好處包括:移植的軟件可以跨平台交付,可能會吸引更多的目標受眾等。
  • 與原生桌面應用程序相比,前端框架和工具可簡化UI開發並縮短反饋週期。
  • Web還帶來了新的可能性,例如深層鏈接以及豐富的UI生態系統的幫助,這些可能會極大改善用戶體驗。
  • 開發人員必須特別注意內存管理、測試和鍵盤操作,以減少移植過程中出現的問題。

谷歌軟件工程師和GDevelop遊戲編輯器的創建者Florian Rival,最近在布拉格舉辦的ReactiveConf 2019大會上發表了演講。他在演講中討論了將一款原生桌面平台遊戲編輯器通過WebAssembly移植到瀏覽器中的經驗教訓。

InfoQ採訪了Rival,詢問了他在這一過程中所遇到的技術挑戰、從移植中獲得的收益,以及開發人員在考慮使用WebAssembly移植桌面應用程序時可以參考的技巧。

圖片
InfoQ:首先介紹一下GDevelop吧。它的目標受眾是哪些? GDevelop對於自身受眾的價值主張是什麼?它為遊戲創作者解決了哪些痛點?

Florian Rival:GDevelop的理念是讓初學者到經驗豐富的遊戲開發人員都可以創作遊戲。 GDevelop允許你使用視覺事件(由條件和動作組成)來創建遊戲邏輯。你還可以通過組合預定義和可自定義的行為來構建遊戲對象。

這樣以來就消除了學習編程語言語法和習語這一入門門檻。對於非開發人員來說,這是一種通過直觀界面快速上手並開始創作的方法。很多人喜歡沙盒遊戲。 GDevelop是一個沙盒——但是你用它可以做的事情是無限的。
對於經驗豐富的遊戲開發人員來說,你將獲得一個集成的開發環境,可以使遊戲的創建工作非常快速且高效(事件被轉換為“真實”代碼),並且可擴展。

最後,對於團隊而言,這是一種使所有人(開發人員、藝術家、項目經理、遊戲設計師……)圍繞一個共同界面協作,並培養所有人創造力的一種方法。

當然,與遊戲創作相關的培訓和講習班使用GDevelop與學生互動也是好處多多的。只需幾秒鐘時間,你就可以開始探索遊戲底層,通過事件來教學編程概念,甚至可以進一步創建擴展。

InfoQ:是什麼促使你將游戲編輯器移植到WebAssembly的?移植到Web會給你帶來哪些在桌面平台無法或很難獲得的好處?

Rival:這款編輯器以前是原生C++桌面應用程序。它正常工作的時候還可以,不好不壞。但它在某些方面開始出了問題:對macOS和Linux的支持很難正確實現(UI工具包中頻繁出現崩潰),並且在UI上的工作進展相當緩慢(因為“做一項更改>編譯>運行>重複”這套循環流程太費時間了),還只能使用過時的UI組件。這些也會給新的貢獻者提高門檻。

在工作中使用React相當長一段時間(以及使用React Native等框架製作移動應用程序)之後,我知道了組件範式(和“UI作為狀態的函數”)是製作接口時的一種非常強大且可擴展的方法。

當時我很懷念這種開發速度及其在原生側實現的出色架構!

總而言之,我開始思考Web技術是否能用來幫助開發出更好的應用程序。

至此,我開始轉向WebAssembly(使用Emscripten),這是將現有的大型C++代碼庫移植到瀏覽器(以及像Node.js這樣的JS引擎)的便捷方法。

我的想法是將WebAssembly用作核心,將JavaScript + React(或另一個前端框架)用作接口,之後我就會擁有一個可移植到幾乎所有現有平台上的應用程序,可在各種設備上一致地工作。我還可以解鎖一些做夢都想不到的新東西,比如說你可以在幾秒鐘內啟動應用並開始嘗試它,或者在手機和平​​板電腦上運行一模一樣的應用。

InfoQ:在談到移植這個話題時,你在演講中提到了以下架構:

圖片

對於一款遊戲編輯器來說,我知道有兩個關鍵模塊,一個是豐富的交互式UI,用於處理編輯這部分工作;另一個是與規則引擎和遊戲代碼生成相關的,更具事務性的算法部分。移植到WebAssembly時這些模塊如何轉換為新的架構?

Rival:移植到WebAssembly的過程中,首先是在原始C++代碼庫中明確區分應用程序的核心(“業務邏輯”,在我的情況下指的是描述遊戲結構的各種類,以及操作這些結構的各種類,還有遊戲代碼生成部分)與UI部分。編譯到WebAssembly的就是這一“核心”部分——除了圍繞文件系統的一些抽像外,編譯後的內容幾乎沒有任何變化。

這一代碼庫能夠跑在瀏覽器中之後,下一步是編寫綁定來將部分代碼暴露給JavaScript。 (所使用的工具取決於你的語言。我這裡針對的是C++和Emscripten,選擇用WebIDL來編寫綁定)。
然後我終於可以用React編寫一個新接口來使用這些代碼了——就像寫了一個新庫一樣。

InfoQ:你遇到的主要挑戰有哪些?對於尋求通過WebAssembly,將現有桌面軟件用類似的方式移植到Web上的開發人員,你有什麼建議?

Rival:熟悉現有代碼庫當然是一個巨大的優勢。最好看看現有的原生代碼是怎樣工作的,如果要移植的是庫,那就看看它是怎樣被使用的。

內存管理是一項很大的挑戰。雖然JavaScript對像是可以垃圾回收的,但你在“ WebAssembly世界”中創建的對象卻並非如此。因此如果你調用一個函數來創建存儲在WebAssembly內存中的對象,然後在JavaScript中刪除對該對象的引用,則只會導致內存洩漏。一定要刪除你創建的內容——直到Emscripten/wasm有了一些垃圾回收器為止。

另一項挑戰是正確使用WebAssembly編譯庫。如果你傳遞了錯誤類型的參數,或嘗試從JavaScript調用一個對象的方法,可是這個對像已經在C++代碼裡從內存中刪除了,那麼你就會身處未定義行為的未知領域(在C++中) ,並且很可能在wasm模塊內遇到“崩潰”。而且你不太可能從中恢復過來(不過JavaScript可能會更寬容一些,並且如果應用程序的非關鍵部分未捕獲到異常,你也有機會讓應用繼續工作下去)。
JavaScript中的類型(使用Flow和Typescript)可能會有所幫助——不幸的是,我還沒找到一種將C++類型自動轉換為Flow或Typescript類型的方法。

調試也可能會更困難。我建議為你的wasm庫準備一個全面的測試集,仔細檢查一切是否正常運行。如果你要將實現轉移到另一種語言上,這會很有用途,並且也會是一份有關如何正確使用庫的實用文檔。

InfoQ:你最後是如何打包/分發Web應用程序的,為什麼這樣做?

Rival:因為這款應用的一項重要特性就是可以訪問文件系統,並且人們希望能夠脫機處理遊戲,因此我將整個應用程序打包為可以在Windows/macOS/Linux上運行的Electron應用。它在所有平台上都運行得很好。儘管Electron的打包尺寸可能有點偏大,但我覺得還可以接受,因為用戶下載的是一款完整的遊戲編輯器。

話雖如此,但製作一款可獨立運行的Web應用也是很必要的,這樣以來應用就可以在線試用和使用了。相比我正在逐漸放棄的桌面版應用,Web平台提供了一些等效的API,或者需要重新尋找一些替代方案,也存在一些局限。

InfoQ:要做出一個最小可行的移植版編輯器(在UI和性能方面)要花多長時間?這個過程的難度如何?

Rival:這樣做的時候肯定會有起伏。在完成可以在瀏覽器內部運行的核心版本後,我和幾個朋友就開始為這款應用程序開發新的基於Web的UI。我們只花了幾週的時間就完成了工作。後來我們又從頭重新開始整個過程——但是我們的原型證明了瀏覽器可以支持這款應用,並能正確運行它。

我確實得在某些時候重新設計綁定,並且升級到Emscripten的較新版本並不總是那麼容易。現在我還沒更新到最新版本上:](但這部分工作需要的只是一些時間)。

當然這並不容易,但是這項工作一開始粗糙的樣子正在逐漸改觀(以前Emscripten的編譯時間非常久,現在就不再是問題了)。

InfoQ:我注意到你提到了移植到Web的應用程序比原來的原生應用表現更好,這讓我很感興趣。能否詳細介紹一下Web應用程序帶來的改進細節?

Rival:有趣的是,移植版的啟動時間有所縮短,我認為還有提升的空間。

我最滿意的是建立這種鏈接的可能性。

點一下那裡,然後在幾秒鐘內(具體取決於你的聯網速度和設備性能),你就有了一款正常工作的遊戲編輯器;你可以用它修改遊戲、運行預覽並開始探究底層細節。在過去想要做到這一點根本就是不可思議的。

從開發體驗來看,應用的C++部分處理起來和之前幾乎沒區別,但是UI的開發確實更快。諸如Storybook之類的工具可以用來獨立地開發應用程序的各個組件——開發時甚至無需運行應用程序本身。開發UI時,我們的反饋循環從幾分鐘縮短到了幾秒鐘。 Storybook還可以可視化應用程序組件的異常狀態(例如錯誤狀態),並在更改後使你能確信一切正常。我認為它們是非自動化的,但仍然是非常有用的測試用例。

不同Web瀏覽器的各種怪癖是不可避免的,但是與我在C++中嘗試過的較老的跨平台UI工具包相比,總體而言在Web端實現多平台支持要容易得多。

雖然應用界面不是由原生小部件組成的,但我們仍然可以使用其中一些部件(特別是如果你使用的是Electron,它可以讓你利用原生上下文菜單和原生菜單欄等功能)。

使用React帶來的干淨的、面向組件的架構在模塊化和保持代碼庫整潔方面有著巨大的優勢——這進一步提升了開發效率。最後這將轉化為更好的界面——因為你的整潔架構將轉化為精心設計的,具備一致性的組件。例如,組件的響應更容易保持一致。很難想像使用舊界面該如何創建響應式UI。

InfoQ:就編輯器的未來功能而言,你有哪些展望?

Rival:內容數都數不過來!社區總是在提議新的事物:]界面總是在不斷改進,以在直觀性和完整性之間取得適當的平衡。我想圍繞軟件創建一個更完整的生態系統和社區——我又想出了很多主意,可以讓幾乎任何人都能更輕鬆,更迅速地製作遊戲。可以在WebAssembly中重做一些影響性能的關鍵組件,或者開發一些帶來新功能的擴展,從而改進遊戲引擎!

GDevelop是一款開源的,跨平台的遊戲引擎,可通過其GitHub存儲庫獲取。

ReactiveConf是面向開發人員的大會,每年舉辦一次,其主題涉及軟件開發的最新技術和趨勢。 ReactiveConf 2019大會於10月30日至11月1日舉辦,是ReactiveConf的第五屆會議。

受訪者介紹

Florian Rival是谷歌的軟件工程師。他是GDevelop(基於WebAssembly和JavaScript的開源遊戲製作軟件)的作者。他還製作了Lil BUB的《Hello Earth》(一款由網紅貓為主角的8位遊戲),支持台式機和移動設備,並100%使用GDevelop製作。總的來說,他喜歡用創新方法來突破我們在應用程序、移動應用和遊戲中可做事情的極限。

原文鏈接

Porting a Desktop Game Editor to the Browser With WebAssembly