3D游戏可以被网页调用已经不鲜见,但反过来在3D游戏引擎中直接支持内部调用网页的引擎并不多,商业性的SL(second life)跟Unreal都可以实现自身支持,并且显示交互效果都不错。SL中的网页交互:
后来在SL供职的一名研发工程师把该技术共享了出来,并使开源的ORGE与Irrlicht引擎目前也能比较好的支持内嵌网页了,这是使用该技术的3D浏览器效果:
相关资料下载:http://www.khrona.com/products/awesomium/
除此之外还有一些比如 torque3D,Unity3D等性价比不错的游戏引擎也提供了有限的内嵌网页功能。
经过笔者的研究,3D场景内嵌网页的技术目前主流的实现方法主要有几种:
l 引擎底层原生支持
这类引擎一般价格非常高,引擎公司研发实力很强,不过即使这样,在实现引擎自身支持内嵌网页功能时,他们也并不是完全自己重写web浏览器内核,常见方案是使用老牌开源浏览器mozilla(firefox用的就是这个内核)的浏览器内核或者使用google公司开源的Chrome浏览器内核,借用这些成熟的浏览器内核语法解析模块,再把浏览器原先的2D图形渲染算法重写成OPEN GL算法,重写事件消息处理模块,使游戏引擎可以完美的支持内部直接调用WEB页面。这种实现原理很简单,但事实上由于是部分借用开源浏览器模块,整合复杂度非常高,整合者需对游戏引擎代码与浏览器内核代码均非常熟悉精通,这样的人目前全世界估计屈指可数,这也是为什么大部分游戏引擎都提供不了原生支持的原因。
l 挂接引擎插件支持
这个技术实现其实跟第一个有类似之处,不过游戏引擎开发者显然不想自己花太多时间精力去做这个工作,而是通过开放游戏引擎源代码或者二次开发接口给引擎使用者,让有闲功夫的使用者去折腾,我曾经花了3个月左右的时间尝试把mozilla浏览器内核整合到torque3D游戏引擎中,整个mozilla浏览器源代码有1G多,经过九牛二虎之力,基本上实现了80%的整合功能,但对于剩下的20%功能,实在是望而却步了,每一个问题的解决都充满着不确定性,没人知道最后到底能不能全部实现100%功能,面对这样的技术问题,一般情况下放弃寻找其他替代解决方案是比较明智的。恰在这时看到了Unity引擎,转而开始研究U3D的内嵌网页技术,可事实上即使翻编了U3D的官网,也只发现MAC下有一个实现案例,而且并不完整,基本上跟我在T3D下做的工作差不多,不过U3D相比T3D来说引擎本身很多地方都做的更好。
l 网页DIV或window支持
在放弃了通过改造引擎实现嵌入网页支持的努力后,我把目光转向了更高一级的方案集成上,由于U3D本身支持编译成网页格式,3D场景在浏览器内运行,很容易让人想到是否网页本身的一些元素是否能覆盖到3D场景之上,从而给人造成一种看起来像是在3D场景内调用网页的效果?马上写了个测试页面,做了个简单测试,发现结果并不乐观,由于网页内的3D场景具有自己独立的窗口,而且DX技术的窗口显示优先级 高于一般的浏览器显示窗口,所以导致浏览器内的元素比如DIV网页层与3D场景叠加在一起的时候,3D场景会把DIV覆盖住。
不过如果就此放弃,那还是可惜了点,于是继续研究,最后发现也不是没有解决方案,一种解决方案就是:
放弃用DIV层,而是采用网页内通过JS代码调用window.open(...)或showModalDialog(…)函数打开新的网页窗口,这样打开的窗口可以覆盖到3D场景之上。
另一种方案是,还是使用DIV层,不过这个DIV层必须经过特殊处理,在DIV层内嵌入一个IFrame嵌入框架,嵌入框架后的DIV比普通的DIV具备更高的显示优先级,可以覆盖到3D场景之上,我索性封装了一个JS类库,使DIV窗口的创建,显示,关闭,移动等功能都可以方便的实现,效果如下(白色区域是DIV模拟出的网页窗口,可以在里面显示任何网页元素,底下区域是U3D的界面):
写到这里,估计有人会问,在3D场景中怎么打开网页上的DIV窗口?这个很简单,在3D场景中调用
Application.ExternalCall,通过该方法调用网页上的JS函数,再在JS函数内实现显示DIV层即可。
那么反过来,怎么在DIV窗口内调用3D场景内的函数或功能呢?这个也很简单,
U3D的WEB 播放器有一个方法SendMessage(…),通过调用该方法,可以向当前3D场景内发送消息,比如SendMessage("Cube", "setstr","你好啊");就可以实现调用3D场景内名字为"Cube"的游戏物体上的"setstr"函数,并给这个函数传递"你好啊"三个字作为函数参数,我们在游戏的"setstr"函数内接收并处理该参数即可。
当然即使我这样说了还是会有人看不懂,这样我也没办法帮你了,慢慢自学更多的基础知识吧。
这个技术的优点是,相对比较容易掌握,并且研发代价较低,充分利用了已有成熟技术,通过简单集成整合,实现了较好的最终效果;并且不需要客户端增加额外的配置或安装额外的插件程序,使游戏应用的大部分交互界面都可以集中到统一的WEB服务器上,传统B/S技术所具备的优点,游戏可以同样具备,后台如果再挂接数据库的支持,想像空间非常广阔。
不过在实际使用中,我发现一个解决不了的问题就是,不管用那种方法打开的窗口,都无法实现透明显示,打开的窗口不管怎么设置,显示效果永远都是不透明的,这样在交互过程中,窗口就会完全遮住后面的3D场景,显得不是很美观,这点可以说是有遗憾的。
l 自定义客户端支持
上面说到的DIV技术有一个遗憾就是不能实现透明窗口效果,这个其实也不是什么大不了的事情,只要游戏功能做的好玩,并不是决定游戏成败的关键因素,不过既然研究上了这个主题,不如再花些时间,看看是否还有其他方案。答案是肯定的,最终我们实现了既可以调用网页,并实现网页与游戏的双向功能函数调用,而且打开的网页窗口还可以实现透明度调节,如图:
这个又是怎么做的呢?说起来也不复杂,我们自己做了一个浏览器,通过调用IE的内核,自己开发了一个自定义浏览器,所以我把这个做法称作自定义客户端支持,当然自定义的浏览器我们并没有地址栏,而是根据我们项目的需要,进行了定制开发,通过这样的定制开发,可以完全抛弃DIV的实现方法,转而用内置子窗口来实现,通过控制子窗口的透明度,可以实现打开的网页的透明度调节,并且也可以实现各种各样的窗口打开关闭效果,同时通过对自定义浏览器进行换肤技术处理,很方便的达到了游戏内置GUI与浏览器GUI的统一风格,通过自定义浏览器可以方便的把U3D的WEB 播放器集成打包到游戏客户端安装包中,玩家需要安装一个5M左右的客户端。自己开发浏览器的技术现成资料应该还是比较丰富的,各位有兴趣可以自己收集。
到这里可以总结一下了,其实U3D在我们项目研发中,只能算是其中一项技术,我们并不完全依赖单一的技术来实现最终的产品,项目会涉及相对较多的技术,我们用JAVA,html,css,javascript等开发WEB页面,数据库用了SQL2005,3D部分用了U3D的渲染,使用VC,DELPHI等开发了自定义浏览器客户端,用了InnoSetup做打包发布,用了CVS做项目版本控制……最终出来的东西是一个技术集成的结果。