游戏内嵌页面通信

叁叁肆2018-10-25 16:39

此文已由作者徐莉授权网易云社区发布。

欢迎访问网易云社区,了解更多网易技术产品运营经验。


最近为游戏做了一套通用的登录注册相关流程的页面。页面运行的环境是Unity3D的内置浏览器。

这个过程类似于我们native app 混合开发类似,不过就像我们有时候为了微信浏览器或者uc做了那么多额外工作一样。他这个组件也有自己的性格脾气。中间也遇到了一些问题,这里总结记录一下,当然,这些绝大部分是依赖于客户端使用的插件版本的。


准备工作

我们游戏中已经有了登录认证相关的的sdk,但是这次为什么要单独做一套呢,可能有一下几个方面的考量:

  • 这个游戏以后主要在海外推广,为了更加贴合老外的使用习惯,所以加入了Facebook, Google Play,ios Game Center等第三方登录,绑定,相关的内容。

  • 同时希望能够为以后更多的游戏服务,做成一个通用的,多语言版本的,并且易于修改扩充和维护的账号中心系统。


这个跟我们平时页面的区别就在于页面运行的壳是Unity3D的uniwebview插件。关于游戏这部分,不过多介绍,只从前端的角度总结一下。


多方通信

前端页面作为一个中间介质,需要跟账号中心后台, 三方认证相关的后台,以及app客户端进行交互。


跟账号中心后台的交互

这个没有什么特别的,主要是安全性上要多考虑一下,比如注册登录时候的用户名密码的传输,防止注册等流程被刷等,这里我们引入了google的验证码模块,这是一个很神奇的东西,大家在用google的时候有时候也会遇到,只需要用户点击一下(频繁操作可能就需要点击图片了,像12306图片那种)因为项目是结合vue框架使用的,所以在使用的时候也做了一部分尝试,这里不再过多赘述,后面有时间也会单独记录一下。


跟三方认证相关的,可以分成facebook和其他两部分。

  • 因为facebook支持纯网页登录认证,所以一切流程都可以在游戏浏览器壳内通过页面的跳转来完成。同时,还支持绑定,换绑等需求。

  • ios Game Centr 是不支持网页接入的。而Google Play 登录接入进来之后,发现,运行在游戏app内的时候,页面直接出提示,说不支持内嵌Webveiw的方式接入,需要使用系统浏览器,更推荐使用app接入sdk的方式。考虑到,如果我们通过修改uniwebview的ua来伪装成一个系统浏览器,可能会在游戏审核过程中有一定的风险,所以最终还是采用了游戏内接入sdk的方式。那么就涉及到页面如何跟app通信了。


页面和app的互相交互通信

app内的首要一个要点是需要做成一个弹框的形式,而不是像微信浏览器,或者我们手游中使用的全屏的,带导航条的。经app的同学的调研调试发现完全可以做到。

因为整个流程是游戏内的逻辑来控制加载相应的页面,所以前端而言,是一个被动的被调用的过程。但通信还是双向的


UniWebview页面发消息给游戏app

在页面以一个a 链接的形式存在。

 <a href='uniwebview://xxx?agr1=aaa&arg2=bbb'></a>

或者前端脚本里面就是重定向

window.href = 'uniwebview://xxx?arg1=aaa&arg2=bbb';

但是页面并不会真的像你重定向到一个新页面一个链出去,而是UniWebview将拦截这种协议开头的内容。并解析为一个UniWebViewMessage对象  ,然后引发 OnReceivedMessage 事件。   一个 UniWebViewMessage 对象包含 一个路径字符串(其中有url 和args 参数字典)。比如上面就会被解析成

path:'xxx',args:  {    arg1: 'aaa',    arg2:'bbb',
}

app端在监听的OnReceivedMessage 事件 的回调中, 会得到 UniWebViewMessage对象,然后就该干嘛干嘛了。这种被称作url方案。


游戏app发消息到UniWebview页面

因为我们的页面是运行在Unity3d中的一个component,所以能够运行页面,也可以运行页面内的javascript方法,通过EvaluatingJavaScript。这样双向通信就没有问题了。其实客户端还可以监听执行情况,当然,这种情况下,一般不需要了。因为这些逻辑都交给页面来处理了。

所以结合上面的需求,如果我想通过ios Game Center进行登录认证,

  • 首先游戏app判断用户的登录状态,没有登录-->弹出前端页面

  • 用户点击了ios Game Center之后,前端页面通过uniwebview://协议告诉App

  • app完成该有的逻辑交互之后,成功了,调用前端的成功的方法,失败了,调用失败的方法。

当然,最终实现的时候,我们也结合其他交互流程进行了一些整理和优化,比如中间过程中的loading的处理,app内有loading,页面上也是要有loading的(不然很可能在跟后台验证的过程中,用户在页面上多次点击,或者操作别的内容),而这两个过程都可以通过游戏内进行统一的loading状态管理。


坑总结

流程定了之后真正做起来,发现中间遇到不少问题,最早就发现,在android的部分手机上首次加载会出现,页面空白,关掉再进来完全正常。因为前端用的rem适配,页面空白很可能是font-size计算的不对,调试发现,app在andorid手机上初次加载有很大概率的拿到body的宽为0,于是所有元素的宽高都是0了。。

于是乎,我们调整了计算font-size的时机,不在刚开始进来就计算,把他延迟到需要的图加载完成,loading动画播完之后,vue组件初始化完成再计算,为了保险起见,给页面加上resize监听,发现页面resize的时候,再计算一下font-size。问题得以解决。

还遇到一个问题,是facebook认证跳到facebook的登录页面再调回来的过程中,会导致uniwebview控件失去焦点,当然,这个就是app要去填的坑了。

这些问题像前面提到了,很大程度上依赖与所使用的插件版本,像手游的那个插件版本就没有页面body宽度计算问题,但是会有js 原生的alert,confirm方法没法使用的问题,关于这个问题,如果要改,需要app复写一些方法才能支持。不过看起来意义也不大,因为毕竟前端这边alert,confirm的替代方案更多更灵活。以后遇到的问题,会持续在这里进行分享,希望大家有问题多多交流。




网易云免费体验馆,0成本体验20+款云产品! 

更多网易技术、产品、运营经验分享请点击


相关文章:
【推荐】 30分钟,让你彻底明白Promise原理
【推荐】 wap html5播放器和直播开发小结