ReactNative在游戏营销场景中的实践和探索-集成

avatar
@字节跳动

作者:字节游戏中台客户端团队 - 熊文源

客户端跨端框架已经发展了很多年了,最近比较流行的小程序、Flutter、ReactNative,都算是比较成功、成熟的框架,面向的开发者也不一样,很多大型App都广泛的使用了,笔者有幸很早就参与学习使用了这些优秀的跨端方案,在这几年的开发和架构设计中,除了在App中支撑了千万级DAU,也慢慢将ReactNative跨端方案运用到了游戏,来提升开发、迭代效率。本次文章我们会分5个章节介绍我们在游戏中的一些探索和实践,相信大家也能从中有所收获:

(本篇为系列第二篇)

上面章节已经聊过游戏环境和App的差异了,也是因为这些特殊性,我们最初的方案采用了ReactNative,官方标准的设计和脚手架工程可以帮助我们很好的搭建一个App,可以帮助开发者在不需要有原生客户端开发的经验的情况下,生成跨端的App。但游戏不一样,拿Unity的游戏来说,游戏的打包、开发环境是Unity的IDE,另外游戏的页面是自渲染的,如何在游戏中显示原生的UI,这些都是要解决的问题,总结下来要在游戏环境中运行ReactNative,要解决几个问题:

  1. 工程化,快速支持ReactNative的调试和集成

  2. ReactNative页面容器,承载并管理ReactNative页面

  3. 支持热更新服务,支持灵活、快速上线业务

因整体原理不复杂,很多文章也做了很详细的介绍,下面就简单说在游戏中的一些差异和思路:

  1. 工程化

  • 在游戏中引入原生端的组件库都是以plugin方式集成,所以首先要将引擎作为一个Module、Plugin集成到游戏中,拿Android举例,将ReactNative sdk封装成独立的aar module,在游戏中引入这个aar作为Plugin,游戏的Native代码能访问我们aar plugin,这点和原生开发其实是一致的
  • 在游戏中很多页面和游戏都是游戏中实现的,所以还需要解决游戏调用native code问题,比如我们需要在游戏中的某个按钮打开ReactNative页面,拿unity来说,就要实现c#代码到ReactNative代码的调用,这里要封装一层bridge,这些都是标准的游戏API,具体可以参考《浅谈Unity与Android原生的桥接》,其他游戏平台也比较类似
  • Debug也是开发调试中必要环境,需要在游戏中引入debug开关和入口,如悬浮窗等,并要做好release包关闭入口
  1. ReactNative页面容器

上面也介绍了游戏都是采用自绘引擎,所有交互都是在一个Activity页面中,任何新的页面的跳转都会导致游戏pause或者stop,打断其沉浸式体验,而ReactNative是在ReactRootView中承载所有的UI渲染的,所以容器的设计思路考虑了以下几种方案:

  • 将ReactRootView加载到游戏Activity的Rootview中,作为一个子View,关闭页面时,从Rootview阶段移除
  • 将ReactRootView封装到系统的Dialog窗口中,这样既可以做到独立窗口加载到游戏中,也不打断游戏进程
  • 有了页面容器后,跳转不同功能的页面,就需要制定一个协议了,通过协议完成页面数据和功能的传递,可以参考开源的Router协议等
  • 活动页面多了后,就涉及到页面之间跳转和窗口管理了,所以需要一套完善的窗口管理API,并通过Unity api,让游戏可以快速通过pop协议或者指定id关闭页面

以下是设计完成后大概能力介绍:

  1. 热更新能力

热更新能力是ReactNative最基础的能力,因引擎支持从asset目录或者磁盘分区中加载JS文件,解决好加载路径和包下载问题,就能很好的支持热更新能力,其中包更新:

  • 考虑引擎的统一性,可以采用native的包下载机制
  • 游戏也支持资源更新,也可考虑将js文件作为资源更新
  • 热更模式一般会支持diff更新、强更、非强更,这些都有比较成熟的框架,这里就不细述了
  1. Common API设计

在实际的业务开发工程中,仅仅靠ReactNative提供的基础API和组件是不够的,比如网络请求,大部分客户端都会有网关,标准的API基本无法满足要求,这里就涉及到要封装自己的API和组件的问题:

  • 基于ReactNative框架提供的ReactBaseJavaModule,完成对一些公共API的封装
  • 基于ReactNative提供的ViewManager框架,扩展一些自定义的原生端组件

但似乎这些还是不够,因为我们是在游戏环境中开发,实际上游戏中或者游戏开发者也需要注入一些API到ReactNative中,供业务使用、扩展,而上述的ReactNative的组件和API架构,对于不熟悉架构的同学来说,会有相当大的学习成本,所以我们基于ReactNative,提出了CommonModule的架构:

  • 不依赖ReactNative SDK,采用系统标准的数据结构和interface实现
  • 提供标准的注册API,将这些interface注入到CommonModuleManager
  • 初始化ReactPackge时,会根据CommonModule生成对应的ReactBaseJavaModule,并完成注册

解决好上述的问题后,基础的功能基本就覆盖了,而且API可扩展性强,当然除了这些外还是不够的,还需要基于基础版本不断迭代,丰富组件、窗口管理、降级冗灾等,以下是我们在游戏中的完整架构:

从架构图中我们可以看到,基本覆盖了游戏活动中需要用到各种API及各种自定义场景:

  • 沉浸式原生体验,与游戏页面活动完美融合
  • 快速、完善的接入、开发、验收体验
  • 模版化的页面搭建,跨平台运行
  • 业务活动热更上线,随时、动态、不发版上线