用于 Unity 和虛幻引擎的 Asm.js 與 WebGL
本文來自微軟,是一個 web 開發系列文章的一部分。感謝你對實現了 SitePoint 的成員的支持。
Unity 以及 Epic 的虛幻引擎,是頻繁被游戲開發者使用的中間件工具,并不被限于去創建被編譯成作為可執行文件運行的應用程序。Unity 之前有一個 web 播放器,它是一個使用了 ActiveX 的可下載插件。Chrome 停止了對 NPAP (網景(Netscape) 插件 API)的支持,但卻在一年前才公布這個消息。
在 4 月份,隨著 Chrome 42 stable 的發布,他們終于把斧頭揮向了他。要說為什么,可以有很多原因,而“掛起、奔潰、安全問題還有代碼復雜性”則是最常被他們掛在嘴邊的。Google 建議轉移到 web 標準支持的技術,比如 WebGL,這種技術我下面會提到。
因為有了 web 技術標準,微軟也正效仿上面的做法,吐槽自家的 ActiveX,VBScript,attachEvent,以及其它傳統的技術。對于 ActiveX 空間的需求已經因為 HTML5時代的功能而減少了很多, 其同樣支持跨瀏覽器間互操作的產生。
隨著 WebGL 和 asm.js 的出現,開發者現在在瀏覽器中就可以充分利用他們計算機設備的能力,并接觸到之前無法企及的市場。在本教程中,我會告訴你他們如何做到這一點的知識:
為什么要編譯成 JavaScript?
JavaScript 是唯一一種能在所有的瀏覽器上運行的語言。盡管只有 JavaScript 將會在瀏覽器上面運行,但你還是可以用其他語言編寫代碼,然后仍然編譯成 JavaScript,如此就可以讓它們運行在瀏覽器上了。這是由一種以 emscripten 而聞名的技術變成可能。
Emscripten 是一種基于 LLVM 的項目,能以 asm.js 形式將 C 和 C++ 代碼編譯成高性能的 JavaScript 代碼。簡言之: 近乎于使用 C 和 C++ 直接運行與瀏覽器里面的原生速度,甚至更好。emscripten 將 OpenGL, 一種桌面圖形 API,轉化成 WebGL,它是這類 API 的 web 變體。
那么這些代碼是如何轉成 WebGL 的呢?
Unity 最近也為他們的運行在 WebGL 上的軟件做了一些基準測試。
然而,讓代碼進行交叉編譯 (經常也被叫做 transpiling ) 并非沒有缺陷。靜態類型語言中發掘出來的通用的性能增強技術,比如多線程 (JS 是單線程的) 以及 SIMD (單指令多數據) 都無法使用。
Mozilla,近來也跟著其他領頭的技術公司搞起 SIMD.js 來,因此性能的提升和處理器使用的降低應該會是不久的未來將發生的事情。點擊這里可以了解更多。出來上述的那些性能上的調整, Unity 還有賴于他們新的腳本運行,IL2CPP (內聯 2 C++)。那是另外一篇文章要講的事情了,不過 Unity 已經在每隔幾個星期就做一個的華麗的系列網站中向諸位呈現 IL2CPP 的功能了。
IL2CPP 擁有兩個獨立的部分:
-
一個預先 (AOT) 編譯器
-
一個用于支撐虛擬機 (VM) 的運行時庫
來自.NET的中間語言 (IL) 經由 AOT 編譯器編譯成 C++ 源代碼。一些諸如獨立于平臺的對線程和文件的訪問,還有垃圾收集器,這些服務和抽象都是運行時庫帶來的好處。
這里就能看到:
圖片來源于 Unity
當 你在一臺 Windows 機器上運行一個 .exe 時,在那個點上它實際上還不是字節碼 (0 和 1). 它仍然還處在 VM 在運行時讀取的一個二進制文件中, 然后才被轉成字節碼。Windows 機器上的 DotNet CLI 就是能讀取這個二進制文件的虛機示例。CPU 除了二進制誰都不認,所以這一額外的步驟是需要的。
仍然感到迷惑? 這篇文章解釋了機器碼、字節碼和VM間的不同之處。
asm.js 是如何適應需要的?
Asm.js,Assembly JavaScript 的簡稱, 它是 JavaScript 的一個自己。一個 asm.js 程序,不管是運行在一個現有的 JavaScript 引擎中,還是一個能識別并優化 asm.js 的預先(AOT)編譯引擎中,其行為都是一致了 — 當然,速度要除外!
速度方面,很難就它與原生代碼的比較進行精確的測 量,而之前對被編譯成 asm.js 的 C++程序所進行的基準測試顯示,一般會比使用 clang 這個面向 C,C++ 以及 Obj-C 編程語言的編譯器所進行的原生編譯慢兩倍,有一點很重要,那就是這一測試是在對單線程程序運行最有利的情況下進行的。下面有更多關于 JavaScript 語言局限的內容。
在 后天, Clang 使用了 LLVM,它是一個用于構建,優化并產品中間甚或二進制機器碼文件 (還是那些0和1)的庫。LLVM 可以被當做一個編譯器框架來用,其中你可以提供 “前端”(解析器和詞法分析器,比如 Clang) 和 “后端” (將 LLVM 展現轉換成實際的機器碼的代碼)
想閱讀更多: Mozilla 的 Alon Zakai 有一個美輪美奐的幻燈片 詳細描述了這是如何運作的。
那么 asm.js 有多酷呢? 好吧它有自己的 推ter 賬戶, @asmjs。不過 asm 的站點有點冷清,它包括 W3C 的文檔,以及一個內容全面的 FAQ。更好的是,Mozilla 在 2014 年對 Humble Mozilla Bundle 進行了整合,讓你可以買到一堆利用 asm.js 的游戲。
為什么不把 JavaScript 轉成 asm.js呢 ?
JavaScript 因為其動態特性,并不能被編譯成 asm.js,并提供諸多好處。當嘗試將其編譯成 C 甚至是 本地代碼 是也會遇到同樣的問題 – 使用了它的 VM 有必要關注那些非靜態的方面。不過,你也可以手寫 asm.js.
如 果有人已經以一種完全靜態的方式對標準的 JavaScript 進行了翻譯,那就有可能會有要使用 asm.js 的需要了。Asm.js 的存在是為了保證不需要開發做出額外的努力就讓 JavaScript 變得更快。讓 JIT 去理解一門動態語言及其靜態編譯器是非常困難的。
為了更好的理解這一點,重點在于理解為什么 asm.js 會提供一種性能上的優勢;或者說為什么靜態類型語言執行起來能比動態的類型語言更好。原因之一就是“運行時類型檢查需要花費時間”而思想更加深刻的一種回 答應該要把對于優化靜態類型代碼的增強特性包含進來。來自于一種諸如 C 這樣的靜態類型語言的終極天賦就是事實上在這類語言的代碼將要被編譯時,編譯器就知道每個對象的類型。
Asm.js 是 JS 的一個受限子集,能很容易的被翻譯成字節碼。為了讓這個子集獲得這種優勢,第一步必須做的就會是需要去分離 JS 所有的高級特性,這會有些復雜。不過 JavaScript 引擎是被優化過的并被設計成能將所有的那些高級特性直接翻譯成字節碼 – 因此像 asm.js 這樣的一個中間步驟并沒有提供太多的好處。
WebGL 是做什么的?
WebGL (Web 圖形庫) 是一套 JavaScript API,使用它無需使用插件就能在任何兼容的 web 瀏覽器上渲染交互式的 3D 計算機圖形和 2D 圖形。WebGL 有三個明顯的優勢:
-
多任務 : 對反光材質或者復雜光照環境的繪制會產生大量的開銷,而鑒于 JavaScript 是單線程的而且受限于 CPU 的性能,為什么將這些任務分一些給 GPU,讓其承擔一些重任呢 ?
-
性能 : 利用(GPU內置于設備中的)硬件加速,WebGL 非常適合用來實現游戲和復雜的視覺效果。
-
著色器 : * * 復雜的視覺效果可以用被稱作”著色器(shader)“的小程序來產生。這可能跟產生一個懷舊的棕色效果,或者對諸如水或者火焰這樣更加復雜的模擬一樣簡單。看看 Shadertoy 所展示的一些例子,它們著實突出了這一點.
當你對一個 WebGL 工程執行 build 操作時,Unity 會穿件一個目錄,里面包含下面這些文件:
-
一個 index.html 文件,將你的內容嵌到一個 web 頁面中。
-
一個 JavaScript 文件,包含面向播放器的代碼。
-
一個 .mem 文件,包含一個二進制鏡像,用來初始化播放器的堆內存。
-
一個 .data 文件,包含了資源數據和場景。
-
一些輔助性的 JavaScript 文件,用來初始化和加載播放器.
你也可以定制頁面的樣式來更好的契合游戲主題,而全屏 API也被推薦用來獲得一個更加身臨其境的體驗。
對學習 WebGL 感興趣嗎? 進入 WebGL 學院 去看看完整的課程吧。
WebGL 少了些什么?
WebGL 是 OpenGL ES 規范的一個子集。這是常見于諸如 Android 和 iOS 等移動設備上面的圖形 API。那個 ES (嵌入式系統) 規范實際上就是 OpenGL —— 用于桌面機器和控制臺的圖形 API,例如 PlayStation 和 Wii —— 的一個子集。 因為 WebGL 并不是一個直接一對一匹配 OpenGL 的東西,所以有些功能特性是沒有的。
這里有一個簡短列表描述了目前 Unity 游戲的 WebGL 版本還不支持的缺失功能特性。我們期待這些都會隨著時間得到改善。
-
運行時生成物質紋理
-
電影紋理
-
除了 WWW 類之外的網絡支持(一個 WebSocket 插件)
-
對于攝像頭和麥克風訪問的支持
-
硬件光標支持
-
大部分非基礎的音頻功能
-
腳本調試
-
線程
-
任何需要動態生成代碼的 .NET 特性
瀏覽器的支持程度如何 ?
這里是問題所在。你可以就在這兒試試在其中兩類瀏覽器中 WebGL demo 的效果。你需要使用支持 asm.js 的瀏覽器。在撰寫此文時,對于 asm.js 的支持情況如下如下:
-
Firefox
-
Chrome
-
Safari
有一點很重要,那就是對于 asm.js 規范在所有的瀏覽器之間并不是 100% 完全都實現了的,因此效果上會有所不同。不幸的是, asm.js 并沒有收錄在時下流行的特性檢查網站 CanIUse.com,因此很難清除的了解其在每個瀏覽器中的支持程度如何。其也不會再移動瀏覽器上面起作用,因為當前它們還不支持 asm.js,盡管其中一些已經部分支持 WebGL 了。在 2014 年 11 月份我寫過一篇關于 《WebGL 在移動設備上的現狀》 。
性能怎么樣?
你可以在自己的瀏覽器上面試試 Unity 的基準測試套件, 看看它們執行從 C# 到 JavaScript 的轉換效果到底怎么樣. 這涵蓋了從 Mandelbrot GPU 測試到 2D 物理以及粒子這所有的東西。在微軟的 Edge 瀏覽器發布之前的,2014 年 10 月的這篇來自于 Unity 的文章,也突出了一些有趣的東西:
-
在幾乎所有的基準測試中,Firefox 的 asm.js 比 Chrome 和 Safari 的都要快,并且是當前運行Unity WebGL內容最好的瀏覽器。
-
當你總是和 GPI 綁定時,可以預期到 WebGL 的執行同原生代碼非常的相近。
-
在一些領域,WebGL 實際上能顯著的跑贏原生代碼。 對于許多依賴腳本性能 (Mandelbrot 和 CryptoHash, 都用 C# 實現了其算法)的測試情況就是這樣,因為 IL2Cpp 可以產生更加優化的代碼 ( 這篇文章中有關于此的更多信息)。
-
對 于要重點優化的多線程和 / 或 SIMD(Unity 5.0 中的 PhysX 3.3 現在完全是多線程的),比如3D 物理測試這些領域,原生代碼仍然能夠比 WebGL 快上幾倍。比起那個,2D 物理方面拿 Firefox 和原生 (Box2D 不是多線程的)做比較則非常的相近了。我們希望未來將帶來面向 JavaScript 的 SIMD 和多線程擴展, 使這里的現狀得到改變。
那么,對于作為的開發者的你而言這有意味著什么呢? 自然有一些領域 WebGL 明顯比原生代碼要慢,比如那些要用到多線程的領域,不過 WebGL 性能還是不錯的,并且只會與日俱增(而不回下降)。事實上,W3C 這個致力于開發 web 標準的國際性的社區剛剛發布了 WebAssembly, 這是一個新的面向 web 上安全代碼的中間表現層。簡稱作“Wasm”, 是一種新的面向底層安全代碼的二進制語法,暫時將會和 asm.js 同時運作。它將會對運行于瀏覽器中的 JavaScript 應用程序進行更深入的性能提升。
Alon Zakai 三月份寫過一篇文章,描述了過去一年主要的瀏覽器中 asm 和 JavaScript 速度整體提升了多少。
為什么會有人想這樣做?
這是一個普遍會被問到的問題。 話雖這樣說,不過我最長聽到的還是 ——“誰會想要下載一個 60MB 大的網站呢? —— 而你是對的 —— 60MB 對于一個網站來說是很巨大的!不過我想同樣是每天從 油Tube 和 Netflix 下載 GB 大小視屏內容的人們也正是那同一群人。如果你把它看作是一個網站,那么它確實很大。不過如果你把它看作是一個游戲程序,60MB 就算是小的了!下面的案例學習所也對此進行了描述。
此外,作為一名開發者的你現在可以繞過應用商店的限制了。想要更新你的應用程序嗎?沒問 題,向你的網站推送一個新的構建就可以了。不想等待 iOS App Store 為期一個星期的審批程序(如果審批通過了的話,那確實就只有一個星期)嗎? 推送更新到你自己的網站就可以啦,完美。
你當然也可以總是用收費墻的形式進行售賣;或者進行某種形式的授權。此外,你無需為應用商店支付許可年費,也無需為他們的商店和系統桌面準備圖片和圖標,等等。現在情況看起來開始吸引人了,而我們僅僅只是觸及了表面。
看看 Illyriad 游戲的團隊在發展期就太空戰斗這個主題所做的。一開始他們的數據流只有一點點,在向你發送額外的數據量之前,這點數據量只夠吸引你過去看看。我相信在我們最后一次談話期間,它開始達到 50MB。你可以在觀看我與他們一起做播客期間更多了解到它。用戶可以立即跳進去并且玩起來 。沒有龐大的客戶端要下載,而進入的門檻也在瞬間被降低了。十幾歲的我也許會在無盡的歲月中一直喜歡著它。
相比之下,傳統的方式在你開始播放游戲內容之前就得一次性的把所有東西都發送給你。當然,游戲主機已經開始使用“塊”了,它會將游戲內容截斷成較小的快,并且幾乎是立即就從你需要播放的那部分開始下載。
Jonas Echterhoff 曾 指出,在 Unity 中, 通過利用 AssetBundles,流式的資源已經是可能的了。或者,你也可以試試這個 Asset Store 包,它會將 WebGL 構建數據進行重新打包,以此來將你的構建中的場景分割成多個文件,而你的內容在第一個場景被加載好就能夠開始播放了:
https://www.assetstore.unity3d.com/en/#!/content/38368
為了專注于星際空間的主題,我曾看過《星際公民》, 其內容看起來將近有 100GB 那么多。說實話你真的相信自己會將 100GB 的內容全部都體驗一遍嗎?
離線體驗
只因為你是指向的一個 HTML5 站點并不意味著你不能擁有一種離線的體驗。不相信我?看看這個來自于 Snowbuddy 的創始人之一 Syd Lawrence 的視頻吧。 在 2015 年的 PhoneGap 日,Syd 運行了《我們做的 Sh 真棒》,并且在其演講期間向我們展示了一些用 PhoneGap 做的很棒的 app,還有他的關于制作高性能 PhoneGap App 的七條建議,而且還特別指出了如何創造出離線的體驗。
讓 你的 APP 能混合利用本地和遠程的內容,這一做法是明智的。像 IndexedDB、localStorage 和 AppCache 這些受到 Microsoft Edge 支持的技術,都能實現這一點。本地的頁面可以放在你的 App 包中保管,那樣仍可以提供一種基礎的離線體驗。
案例分析: Owlchemy 實驗室的 Aaaaa! 被從 Unity 轉成了 asm.js
Owlchemy 實驗室的團隊已經在 2014 年對他們的游戲 Aaaaa! 進行了轉化,并且 就這一過程組織了一篇不錯的分析評論文章。 使用去年 6 月釋出的 WebGL 預覽版本,他們已經能夠利用已有的 C# 代碼,將其轉成一個 JavaScript 文件,這個文件有超過 100 多萬行那么長的代碼!
Aaaaa! 有級數超 200 ,在運行時會有超過 300 個資源被產生出來,此外還有 38 首完整的歌曲。在 PC/mac 上它們看起來就是一個 300MB 大小未壓縮的文件,所以你可以想象的到,要是每次想要玩這個游戲都得下載所有這些東西應該會比較麻煩的。
對存儲的節約最大的來源之一就是 Unity 的音頻剪輯流媒體方案,它可以在運行時按需處理音樂流。完成時,它們最終被壓縮的 WebGL 構建大小,包括了所有載入的資源還有 Unity 引擎本身,結果是 68.8 MB。壓縮后的獨立 PC 構建是這個大小的 3 倍,也就是 192 MB。
當 然有一些 UX 上的變更需要做,包括重新綁定 ESC 鍵,它在許多游戲中應該映射的是一個暫停菜單,但在瀏覽器中則會是退出全屏并解除對鼠標的鎖定。此外,因為瀏覽器的安全模型會強制讓這些游戲沙盒化,所以 在將數據塊保存到磁盤上或者從用戶的硬盤上加載自定義音頻時可能會有問題。
最后,考慮支持某種形式的云同步特性是重要的,因為游戲玩家常常不會只在同一臺機器上玩基于 web的游戲。對于一個消費者而言,可以從任何機器上載入他們的存檔并且會顯示設置/保存,這樣會更加方便。
還有其它中間件工具利用了這個東西嗎?
Epic 的虛幻引擎4(Unreal Engine 4)也可以導出到 WebGL 并且利用上 asm.js。你可以在這里找到一步一步的指南。 其過程除開首先處理 C# 的那一步——因為使用虛幻引擎編寫的代碼已經是 C++的了——幾乎就是一樣的。
Epic 現有的演示片段有 Tappy Chicken,一種類似于 Tappy Bird 類型的游戲,在 iOS 和 Android 上也可以玩。他們在 GDC 2014 上面首先展示了運行于 Firefox 的 UE 4:
在這之前一年的 GDC 中, Mozilla 和 Epic 在他們其中的一次演講中讓所有人都吃了一驚,因為當時他們發現僅僅只在其 Epic Citadel Demo上工作一周之后 UDK (虛幻引擎 3) 就可以運行在瀏覽器中了。
來自于 NomNom 游戲的《瘋狂的怪獸(Monster Madness)》是第一個使用 asm.js 在 Web 上發行的商業虛幻引擎3游戲。
未來前景怎么樣?
WebGL 的應用并不只限于游戲。應用程序其實也可以很容易的利用上這項技術。
看看這個《虛擬巴黎(Unreal Paris) 1.2》的 Demo,用戶在里面就可以漫步于一個精心設計的公寓。(下載鏈接)
想象一下作為一名建筑師或者設計師在嘗試向客戶進行推銷。你可以在匆忙中讓它運行起來,就在瀏覽器里面。甚至更好,用戶并不需要下載整個應用程序。
瞧瞧像《Age of Ascent》這類東西。下載 54 MB 你就可以開始把玩這種應用程序了,因為它只下載你當時需要的數據流,并且能使用一種諸如 IndexedDB 的技術將其緩存到本地,所以并不需要你再下載一次。用戶在幾秒鐘之內就可以啟動并運行起來。在十二月的時候我采訪過 Ilyriad 游戲的團隊 ,更好的了解到他們是如何把技術組合到一起的。
在另一個極端, 我們有《星際公民(Star Citizen),它有 70GB。對于許多人而言要進去這就是一個巨大的障礙,特別是在一些地方可能并沒有快速的寬帶。
對于那些可能不想使用 C 或者 C++ 來編寫其應用程序的開發者而言,仍然可以使用一種 WebGL 框架并且全部用 JavaScript 編寫它。BabylonJS 就是這樣的一個例子,它包含了一個 2D 和 3D 應用程序都支持的物理引擎,還有 handJS,它能將所有的輸入類型 (點擊、觸摸、觸控筆) 都匯集成指針時間。
還有其它的選擇嗎?
當然有啦! PlayCanvas 是一個很棒的基于 WebGL 的框架,其物理上運用了 asm.js。其甚至于表現更好,因為它擁有優秀的文檔和教程,就在一個基于瀏覽器的編輯器的頂部。
對于這樣的工具,你應該不需要使用某種類型的封裝 (比如 Cordova 或者 PhoneGap) 來將應用導入注入 Google Play、App Store 或者 Windows Marketplace 這樣的應用商店。
ManifoldJS 的目標是通過利用 Web App 清單(支 持 web 站點聲明 app 風格的屬性)讓移動開發者的生活比以往更輕松。ManifoldJS 會針對支持它的平臺使用那個標準,而對于那些不支持的就回退到 Cordova。Cordova 是不錯,不過 W3C 也考慮過在 Mozilla 上就能跑得起來(Firefox 打開 Web App), Google (以 Chrome 為容器的 App) 還有 Microsoft 已經支持了(Windows 8 有本地Web 應用, Windows 10 擴展到能容納 web 應用)。基于此,我們現在就能夠包裝一下網站并傳出出能夠被部署到不同 APP 商店中的混合應用程序了,當然仍然可以利用到每種設備上許許多多的本地原生特性(聯系人、日歷、文件存儲、陀螺儀、 GPS,等等。)
Jeff Burtoft 在 http://www.thishereweb.com/hosted-web-apps-explained/ 中對托管的 web 應用進行了很好的描述。
當我們將兩者結合起來的時候,我們可以創建出擁有原生運行速度的應用程序,它可以被部署到許多的 APP 商店中,并且使用的基本上就是一套代碼庫。對于移動開發而言沒有銀彈,但是這樣做確實讓過程更加容易了。
總結
Unity 在它們的文檔中概括了將資源導出到他們的 WebGL 播放器的過程。WebGL 和 asm.js 都支持的瀏覽器還在持續的增加,而 Firefox 甚至在今年較早的時候在 San Francisco 舉辦的 游戲開發者大會上展示了 WebGL 2.0 的特性。WebGL 2.0 帶來了許多提升,包括一次渲染 32 個紋理的能力,相比之下目前的標準支持的數量是 8,此外開發者還能使用到抗鋸齒和多目標渲染功能。
將 Unity 游戲移植到 WebGL 的優勢有很多:
-
多渠道發布而不限于應用商店
-
更小的包大小
-
容易展示和共享項目
如 Aaaaa! 案例分析以及Mozilla Humble Bundle所闡明的,開發者已經證實了該模型是有效的,所以就是我們利用瀏覽器終于可以提供的為我們的工作帶來更多優勢的好時機。
更實際的使用 JavaScript
本文是來自于 Microsoft 技術傳道者實踐 JavaScript 學習的Web開發系列的一部分,涵蓋了包括 Microsoft Edge 瀏覽器和新的 EdgeHTML 渲染引擎 有關于互操作性的最佳實踐。
我們鼓勵您利用 dev.modern.IE 上的免費工具來對包括 Microsoft Edge —— Windows 10 上的默認瀏覽器——在內的瀏覽器和設備進行測試:
從我們的工程師和布道者那里深入了解 Microsoft Edge 和 Web 平臺上的技術:
-
Microsoft Edge Web 峰會 2015 (旨在展望新的瀏覽器,新的 web 平臺標準的支持,以及來自 JavaScript 社區的嘉賓演講)
-
哇哦,我可以在 Mac 和 Linux 上測試 Edge & IE 了! (來自 Rey Bango)
-
推進 JavaScript 而不破話 Web (來自 Christian Heilmann)
-
讓 Web 正常運作的 Edge 渲染引擎 (來自 Jacob Rossi)
-
使用 WebGL 發揮 3D 渲染 (來自 David Catuhe ,包括 vorlon.JS 和 babylonJS 項目)
-
托管 web 應用和 web 平臺的創新 (來自 Kevin Hill 和 Kiril Seksenov,包括 manifold.JS 項目)
更多免費的用于 Web 平臺的跨平臺工具和資源:
本文地址:http://www.oschina.net/translate/asm-js-and-webgl-for-unity-and-unreal-engine
原文地址:www.sitepoint.com/asm-js-and-webgl-for-unity-and-unreal-engine/