作者:字节游戏中台客户端团队 - 熊文源
客户端跨端框架已经发展了很多年了,最近比较流行的小程序、Flutter、ReactNative,都算是比较成功、成熟的框架,面向的开发者也不一样,很多大型App都广泛的使用了,笔者有幸很早就参与学习使用了这些优秀的跨端方案,在这几年的开发和架构设计中,除了在App中支撑了千万级DAU,也慢慢将ReactNative跨端方案运用到了游戏,来提升开发、迭代效率。本次文章我们会分5个章节介绍我们在游戏中的一些探索和实践,相信大家也能从中有所收获:
- 第一篇:游戏中使用ReactNative的背景介绍
- 第二篇:简介游戏中怎么集成ReactNative
- 第三篇:简介游戏中的ReactNative性能优化
- 第四篇:ReactNative Hermes引擎简介
- 第五篇:ReactNative 新架构介绍
(本篇为系列第一篇)
ReactNative是目前比较流行的跨端方案,目前支持Android、iOS、Windows等平台,能解决了开发中的人力和双端统一性问题,支持热更新,做到了随时随地上线。提到ReactNative,大家一定会和Flutter去做比较,Flutter同样是比较通用的跨端框架,两者各有优缺点,围绕着两者之间的讨论也挺多的,但对于开发者而言,在合适的场景中选择合适的更重要,后面我们也会介绍在游戏中,我们是如何使用ReactNative完成一些活动页面的开发的。
ReactNative作为跨端框架在原生端App中使用比较多,从国外的Facebook到国内各大大厂都在使用,而且基于该设计思想的跨端框架也不少,如weex等,而在游戏中使用的还比较少,主要原因还是游戏的开发、运行原理与原生差异太大。目前游戏的运行环境有很多种,主要以Unity、Cocos、UE4为主,而且这些游戏平台已经具备了跨移动端平台的能力,同时支持Android、iOS等设备,且具备热更新能力。
在原生App开发中很多快速迭代的页面都采用了H5开发,主要集成、开发起来简单,游戏中也比较类似,这些H5页面也做到了多平台同时支持,但在响应速度、启动速度、内存等性能指标上会显得有点不足,而且在游戏环境中很难做到沉浸式的体验。所以围绕着解决活动快速迭代、发布、高性能、沉浸体验等问题,业也做了不少解决方案,参考、学习这些经验我们也做了大量的对比测试,在早期的方案上最终选定了ReactNative作为基础引擎。
游戏环境简介
- 自渲染引擎:现在的游戏一般都是基于opengl设计,自建的UI渲染引擎,将UI内容更新到原生的surface来显示,所以和原生的UI组件体系差别较大,原生端的系统组件不再适用,且整个游戏在Android设备上是一个Activity,另外游戏自渲染引擎提供了很多动画属性,来满足高质量的动画体验及沉浸式体验,这些在原生侧都是无法共享的。
- 开发语言差异:在开发语言上也存在很大的差异(如Unity C#/Lua等),不同于Android、iOS的系统开发语言、IDE,相对客户端,参与这方面的开发者也比较少,这也限制了很多原生框架在游戏中的使用,当然游戏也是需要访问设备的一些资源的,这就是常说的bridge,游戏通过bridge来调用系统或者开发者提供的API,UI上仍无法直接共享,虽然网络上也有一些纹理共享的方案打通游戏和原生UI,但使用上仍然有很大的局限性
- 性能要求高:游戏相比于app来说对画质、渲染性能要求较高,这也导致了自身对内存、CPU占用较高,对于接入的业务、页面的内存峰值、稳定值方面要求比较严格,最好能做到退出页面即释放
- 热更能力强:游戏一般都支持热更能力,如Unity,本身就支持JavaScript和Lua开发,所以存在unity+Lua的热更方式,且很多活动或者游戏业务都会采用热更和动态入口方式,减少安装包大小,提升灵活性
- 支持设备复杂:游戏的运行环境除了常见的Android、iOS平台外,还存在PC、Android模拟器等,所以在兼容性和体验上要求比常见的app要高。测试发现现有的Android模拟器一般都是采用x86架构,支持32及64位,而手机设备一般是arm v7、v8,虽然模拟器也支持了v7、v8兼容模式,但都是通过arm转intel指令完成,实测存在很多兼容问题,支持起来难度比较很大
选择ReactNative
从游戏端内的数据来看,除了游戏本身核心外,一些活动、功能都是需要快速迭代的,因此端内用了很多h5的活动场景,且为游戏提供的大量的API和数据能力,但在内存、性能、沉浸式体验上与游戏仍有很大的差距;另外因游戏、H5与原生端方案的差异,原生UI组件无法在游戏中直接使用,需要开发实现,这点比较类似于Flutter,所以为了能更好的兼容原生端的一些能力、场景,选择能支持系统UI交互、跨不同游戏平台,是我们选择的首要考虑条件。从技术上来看,有游戏内的解决方案,有客户端的解决方案,在考虑选择方案时,我们主要考虑了以下几个问题:
- 游戏拥有很多不同的平台,而且开发语言不一致,采用游戏端内方案,就会涉及到维护多套引擎的问题,很难做到架构统一性,比较流行的如xLua、PureTS等
- 客户端比较流行的跨端方案比较多,上面说的h5页面就能很好的解决跨平台问题,也是目前很多游戏活动采用的解决方案,但因为其性能、体验与原生客户端的差异,才有了后来Facebook对外开源的ReactNative方案,它很好的支持了统一的原生体验,并大大提升了性能,引领了大前端的浪潮。现如今发展比较迅速的Flutter,自渲染引擎和UI一致性,也逐渐被很多大厂App采用;另外国内友商也提出了自己的跨端方案Weex,原理上与ReactNative类似。
为什么没有选择Flutter、weex作为我们游戏端跨端引擎呢?相比而言Flutter的工程化较为复杂、整体偏重,而且很难适应游戏和活动业务分离开发的场景,而weex因为生态与ReactNative的差距,也不在我们视角之内;另外游戏端内的xLua+Unity、及腾讯已开源的pureTS也是业内用的比较多的方案,我们也一起做了对比分析:
ReactNative | Flutter | xLua | PureTS | |
---|---|---|---|---|
开发语言 | React | Dart | lua | TS |
运行环境 | JS(JSCore、hermes) | Flutter engine | unity | unity+JS(Qucik js) |
支持平台 | Android、iOS、web | Android、iOS、web | Android、iOS | Android、iOS |
生态 | 丰富(react) | 较少(dart) | 较少 | 较少 |
代表App | 京东、美团、携程 | 闲鱼、美团 | unity游戏 | 腾讯潘多拉 |
热更能力 | 支持 | 需改造(android) | 支持 | 支持 |
稳定性 | 稳定(2015发布) | 较稳定(2017发布) | 稳定 | 较稳定(2020发布) |
工程化 | 简单 | 难 | 中等 | 中等 |
学习难度 | 简单 | 中等 | 难 | 难 |
UI组件 | 丰富、原生(生态+自研) | 较少(skia) | unity组件 | unity、ue4组件 |
开发工具 | 方便(vs code) | 依赖原生IDE | unity IDE | 方便(vs code) |
动画、渲染 | 较丰富 | 丰富 | 丰富 | 丰富 |
适合场景 | 全页面、弹层 | 全页面 | unity页面 | unity页面 |
其中xLua、PureTS采用的是游戏端内的UI渲染,在游戏内部是比较成熟的方案,之所以不在我们前期的评估的范围之内的原因如下,也不是方案不好,而是不适合,当然采用ReactNative 原生端方案也有局限性,如UI无法和游戏混排,这也是为什么完成ReactNative搭建后,也开始持续迭代支持了PureTS方案的原因,具体原理这里就不解释,这是一个开源项目,原理不算复杂:
- 两者采用的是游戏UI组件,开发者必须对游戏本身的设计和架构有很深的了解,比较适合有丰富游戏开发经验的团队,而我们是客户端团队
- 这些方案都是针对某个游戏平台而设计,不具体全平台统一性,需要大量适配支持Cocos、Unity、UE4等平台,维护成本较高
- 很难复用客户端很多复杂的组件,例如地图、直播、地图等等的组件,这些在游戏中就不支持,自然这些方案也很难支持
相信大家还是会有疑问,选择ReactNative感觉不是一个最好的选择,相比于Flutter的最近的突飞猛进发展,ReactNative逊色了太多,这两年进展微乎其微,而且渲染性能的瓶颈也越来越制约了其发展,先后有很多开发者都宣布不再开发、维护ReactNative,转向原生开发或者Flutter的怀抱,但我们最终还是坚定的选择了reactnative,更看好其未来的架构发展,详细大家可以参考我的文章《庖丁解牛!深入剖析React Native下一代架构重构》,同时在后面的章节中,也会为大家重点讲解新架构的特点。