做者:小玉
連接:https://zhuanlan.zhihu.com/p/19974794
來源:知乎
著做權歸做者全部。商業轉載請聯繫做者得到受權,非商業轉載請註明出處。
隨着Unity5.0的發佈,WebGL平臺的部署也正式登場(目前還處於Beta狀態)。WebGL是一項利用JavaScript API呈現3D電腦圖形的技術。區別於其餘須要瀏覽器加載插件的形式(好比Flash和Unity的Web Player),經過使用WebGL技術,咱們只須要編寫簡單的網頁代碼便可以實現3D圖像在瀏覽器中的展現。使用WebGL的好處是顯而易見的:在玩遊戲以前無需下載任何插件,打開瀏覽器,輸入遊戲地址,就能夠直接進行遊戲了。並且WebGL的這套JavaScript API透過瀏覽器直接和系統的顯卡打交道,效率也能夠獲得保證。
WebGL在Unity中的實現
具體到技術細節,WebGL在Unity中是經過IL2CPP,Emscripten和asm.js這幾大關鍵技術來實現的。
- IL2CPP:將腳本代碼翻譯成C++代碼的模塊。具體細節在上兩篇有詳細的討論(上、下)這裏直接略過。
- Emscripten:將編譯後的Byte Code翻譯成Javascript,經過這個步驟之後,代碼就能夠在瀏覽器中直接運行了。雖然Emscripten大多數狀況下是翻譯c/c++的代碼(在Unity中的使用狀況就是如此),可是它也能夠接納任何由符合LLVM標準的編譯器生成的其餘語言的Byte Code,將其轉換成JavaScript。
- asm.js:相比前面兩個模塊,asm.js是最有趣的部分。也是Unity用來保證WebGL遊戲運行效率的關鍵。他的主要做用就是對Javascript進行優化!提升JavaScript在瀏覽器中的運行效率。後面咱們就具體的講講asm.js是如何作的。
ASM.JS
此次咱們先直接看代碼比較:
先來個簡單的C代碼:
int f(int i){
return i+1;
}
相應的asm.js代碼:
function f(i){
i=i|0;
return (i+1)|0;
}
能夠看到咱們在每句後面都」比特或」上了0,這個操做對原來的變量裏的值沒有任何影響,看上去是無用的操做。可是它卻保證了咱們代碼裏的i和(i+1)都是整數而不是其餘類型。
另一段:計算字符串長度
size_t strlen(char *ptr){
char*curr = ptr;
while(*curr !=0){
curr++;
}
return(curr-ptr);
}
相應的asm.js:
function strlen(ptr){//calculate length of C string
ptr=ptr|0;
var curr=0;
curr=ptr;
while(MEM8[curr]|0!=0){
curr=(curr +1)|0;
}
return(curr-ptr)|0;
}
在代碼中,MEM8是一個Byte類型的「View」,用來操做實際的」typed buffer」。(在這個例子中是ptr指向的內容。有關View和typed buffer的概念請參考 JavaScript typed arrays)
相似的處理出如今asm.js的各個地方:asm.js中包含了JavaScript的一個嚴格子集 —— 包括嚴格類型的整數、浮點數、數值計算、函數調用和堆訪問,使得其在被執行的時候跳過了致使JavaScript變緩慢的動態轉換和其餘一些操做,大大加快了速度。
咱們能夠在代碼中加入「use asm」開關開嘗試開啓asm.js模式。
function MyAsmModule(){
"use asm"
//module body
}
asm.js有一套本身的規範(具體能夠參考這裏),你徹底能夠本身手寫asm.js代碼,但更多的狀況是利用上面提到的Emscripten自動的生成代碼。
若是瀏覽器支持asm.js,那麼程序的代碼會獲得加速,可是若是瀏覽器不支持asm.js,也無需擔憂。asm.js本質上是JavaScript的一個子集,它用到的全部語法和JavaScript徹底一致。在不支持asm.js的瀏覽器上執行的效率和通常的JavaScript腳本是同樣的。目前支持asm.js的瀏覽器只有FireFox一家。IE和Chrome也在積極跟進。按照微軟的說法,在Windows 10中所使用的Chakra引擎將支持asm.js,而且微軟正與Mozilla進行合做,以爭取儘快實現它。Chrome則將經過TurboFan這一在V8上通過優化的編譯器提供對asm.js的支持。若是你的Chrome版本是41,這意味着其已經內嵌的TruboFan Beta版,能夠加速asm.js了。
Unity例子測試
首先你得有Unity5.0,使用官方或者本身的項目,切換到WebGL平臺。我這裏用的是官方的Space-shooter,將編譯好的整個包放入到Web Server的目錄中,而後在瀏覽器訪問。
在瀏覽器中打開項目的Html頁面,找到並打開WebGL_Build.js,發現其中除了少許能夠閱讀的函數之外,文件的絕大部份內容都是相似用匯編形式寫出的asm.js代碼。
咱們遊戲的絕大部分邏輯代碼就出如今此
總結
Unity5.0中的WebGL平臺部署是一個使人激動的選項,純html的方式運行遊戲意味着咱們能夠把更加複雜和有趣的遊戲直接部署在網頁上。讓其在諸如微信這樣的平臺上直接傳播。
這個魔術的背後離不開IL2CPP,Emscripten和asm.js。asm.js有着化腐朽爲神奇的力量,經過一套工做流轉換,使咱們得到高效的代碼。
高效的代碼只是其中的一個好處,另一個好處是代碼混淆:因爲asm.js的天性使然,這些看上去像極了彙編的代碼很好的解決了html5遊戲客戶端源碼直接暴露的風險。這一點對於商業遊戲來講也很是重要。能夠說asm.js天生就是爲了WebGL遊戲準備的!而從各大瀏覽器廠商對其支持力度也能看出之後的流行非它莫屬。其實Emscripten+asm.js不光光是Unity可使用,其餘引擎也同樣可使用。例如Unreal3也使用一樣的方法來將遊戲帶到瀏覽器上。而cocos2d-x也有嘗試使用該技術。WebGL的前景一片光明。