Unity3D将来时:WebGL

Unity3D将来时:WebGL

小玉小玉

作者:@Xu Bowie


随着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代码。
    在浏览器中打开项目的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也有
    高效的代码只是其中的一个好处,另外一个好处是代码混淆:由于asm.js的天性使然,这些看上去像极了汇编的代码很好的解决了html5游戏客户端源码直接暴露的风险。这一点对于商业游戏来说也非常重要。可以说asm.js天生就是为了WebGL游戏准备的!而从各大浏览器厂商对其支持力度也能看出以后的流行非它莫属。其实Emscripten+asm.js不光光是Unity可以使用,其他引擎也一样可以使用。例如Unreal3也使用同样的方法来将游戏带到浏览器上。而cocos2d-x也有尝试使用该技术。WebGL的前景一片光明。

    欢迎关注IndieACE微信公众号:IndieAce,可以看到IndieACE定期分享的好内容。

    需要转载IndieACE的文章请与我们私信联系。

文章被以下专栏收录
6 条评论
推荐阅读