游戏全球发行提效-- 发行 iOS SDK的自动化接入探索

  金牌会员 | 2024-6-21 13:44:51 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 783|帖子 783|积分 2349

本期作者




1、前言


游戏SDK作为游戏技术中台赋能游戏研发的核心产物之一,其核心能力包括账号、生意业务、合规(实名、防沉迷),以及社交、营销等能力。为游戏开辟者提供了便捷的方式快速完成底层业务能力的搭建,低沉开辟和维护的难度。资助游戏研发更专注于游戏内容的创作,缩短游戏研发周期的同时保障游戏的安全性合规性。

2、背景


为了更有效的满足差别地区市场的策略和法规要求,为差别地区提供符合当地玩家喜欢的游戏体验,哔哩哔哩游戏在发行上采取差别化的运营和推广策略。
游戏在发行中会按地区和主体分包发行,我们将游戏的主体和地区发行方案称为发行计划。
游戏SDK作为游戏的底层业务支撑,为了适配游戏的发行计划,也提供了与之对应的游戏SDK。



随着游戏业务的发展,游戏SDK的数量也不绝增长。在保障游戏业务发展的同时,我们整合了全部外洋发行的SDK,游戏在外洋发行中不必要根据发行地区接入对应的地区包,只必要接入全球版游戏SDK即可。
这在很大程度上提高了游戏外洋发行的效率,但并非最优解,在高效支持游戏差别化发行的同时,我们不绝在思考怎样更好的提拔全球化发行效率。

3、定个小目标


基于当前的游戏业务情况,我们设想了一个比较理想的SDK接入景象:

  •  一次接入,全球适配:我们希望游戏只需接入一次SDK API,就能够轻松实现全球范围的适配工作。
  • 即拿即用,无需配置:研发无需配置游戏SDK所必要的参数,由工具自动化完成SDK的配置工作。
在当前游戏分主体地区运营策略下,如果能整合全部SDK的接入并且简化接入步调的话,这对游戏的接入提效无疑是巨大的。

4、 方案选择


1、重构现有游戏SDK,合并全部SDK


在过往的游戏业务中,我们一度维护超过20款SDK。经过两次业务重构后,SDK已缩减为6个。
由于国服和外洋服的业务差别和合规要求,以及发行主体间的合规要求,SDK已无法再缩减。
在当前游戏的全球化发行的路程中,最好情况只必要接入两个SDK,但不能清除接多个SDK的情况。
在当前政策和汗青技术的要求下,合并全部SDK已然不是一条能走通的路。

2、在游戏SDK的上层设计聚合SDK,通过出包工具自动化接入


聚合SDK在游戏行业是比较常见的业务模式,在安卓发行中较为常见,它可以资助开辟者减少对接华为、小米、应用宝等渠道SDK的研发资本。
在我们的业务场景中,聚合SDK的任务是同一bilibili游戏业务中的各个游戏SDK,在产物上输出聚合SDK供游戏研发接入。
聚合SDK会根据游戏的发行计划在内部完成相应游戏SDK的接入和调度,原有的游戏SDK则退居二线,研发无需感知具体接入的游戏SDK。
聚合SDK完成全部游戏SDK的功能合并,对外提供同一的API。在游戏完成API接入后,由打包工具完成底层游戏SDK的接入和配置。

5、怎样做?


5.1、OneSDK同一API


虽然各游戏SDK在业务逻辑上处理方案不一致,但对外提供的业务能力大抵类似,比如账号体系、付出能力、客服、广告归因等能力都是通用的。这给顶层的聚合SDK——OneSDK的开辟提供了先决条件。
在顶层设计上,OneSDK最大大概的合并和简化各个游戏SDK的参数差别,同一各个SDK的API定义,给游戏提供同一全面的API接口。
在业务分工中,OneSDK不直接参与游戏业务,在顶层API和底层业务SDK中充当桥接作用,当调用OneSDK API时,通过AdapterProtocol寻找可以相应API的游戏业务Adapter。
实际游戏SDK业务调用的工作在Adapter层面完成,每个游戏SDK有本身的Adapter,Adapter根据游戏SDK的特性完成参数的转换和适配,最终调用到实际的游戏业务中。



后续游戏在SDK的接入过程中,只必要接入OneSDK即可完玉成球范围的发行适配工作,无需感知底层游戏SDK。
我们通过OneSDK完成了的各游戏SDK的聚合,在API层面上完成了同一。但Xcode工程的接入配置中,照旧必要实际接入对应的主体游戏SDK,SDK所必要配置仍然是必要的。
怎样资助游戏快速完成底层游戏SDK的接入配置,是我们下一步必要思考的事变。

5.2、打包工具实现自动化接入


在接入OneSDK后,在API层面上已经无需感知底层SDK,在配置上我们也必要有相应方案资助游戏克制繁复的SDK配置工作。
既然SDK接入配置无法克制,我们决定设计一款打包工具,通过脚本替代人工完成全部SDK的配置和接入工作。
在安卓中有着和iOS平台上类似的场景,在安卓中有多渠道发行的场景,一套代码必要发行谷歌、华为、小米、应用宝等差别的渠道。
对于这种情况安卓游戏SDK可以使用官方提供的APKTool工具,反编译更换SDK文件后,再回编译生成各个渠道包。



那边iOS可否像安卓一样修改母包IPA,更换相关代码和资源文件最终生成新的IPA包呢?
很遗憾,这种方法是不可靠的。iOS没有像谷歌一样官方提供的APKTool工具,来执行反编译和回编译的能力。
要想在iOS实现一套代码自动完成多渠道发行的打包,我们可以比安卓更早一步介入打包的流程中。
安卓是在源码编译成APK包体后介入打包的,我们可以在源码阶段介入,通过修改Xcode工程的方式,完成多渠道包的自动化接入。

5.2.1、打包工具设计


考虑到游戏的Xcode工程动辄几十G的巨细,上传下载十分耗时,以及游戏研发对源码工程泄露的担忧。打包工具在产物形式上以MacOS端的应用交付给游戏研发使用,在当地完成游戏的打包工作。
简而言之,打包工具的主要功能是在完成鉴权后,获取与发行计划对应的打包计划,然后根据该计划完成OneSDK下层的游戏SDK接入和配置。
在应用层面,(被苹果原生MacOS开辟框架短暂折磨过之后)我们选择对客户端开辟更为亲近的Flutter作为框架,对于轻量级的应用,Flutter同一的API体验、热重载等特性可以资助我们快速完成应用的搭建。
在偏底层工作的Xcode工程编辑上,Flutter没有十分稳定的类库可以完成Xcode工程的编辑工作,但可以调用脚本完成前述工作。
脚本所要做的工作,可以简朴归纳成以下步调:
1. 删除游戏SDK文件夹以及内里的内容
2. 导入新的游戏SDK文件
3. 修改Info.plist文件,添加业务参数
4. 修改build-settings,添加指定编译指令
5. 导入游戏SDK所依靠的系统库



在脚本框架上,我们使用Xcodeproj模拟在Xcode界面完成的代码、资源的删除&更换操作
Xcodeproj是一个常用的修改Xcode工程的Ruby框架,由我们熟知的Cocoapods团队开辟。其内部完备映射了project.pbxproj的Object范例及其对应的属性。将Xcode项目文件解析成一个抽象语法树(AST),通过遍历语法树来获取项目配置信息,并提供相应的API来修改和管理这些信息。通过代码来添加、删除、修改项目中的文件、依靠、编译选项等,以到达自动化接入的目标。

5.2.2 project.pbxproj 先容


要想通过脚本修改Xcode工程,我们先要了解project.pbxproj文件。
project.pbxproj被包装在xcodeproj文件中,存储着Xcode中全部能瞥见的公共配置信息。它本质上是一种旧风格的 Property List 文件,汗青可追溯到 NeXT 的 OpenStep。
换句话说,我们可以通过修改project.pbxproj来实现我们在Xcode中可以修改的配置。
信赖许多人都有因为代码冲突而手动修改过project.pbxproj,也为project.pbxproj繁杂的内容感到眼花缭乱。这是因为project.pbxproj文件的可读性较差且内容较多。实际上project.pbxproj有固定的布局和格式,了解大抵布局和分类用途就会对其认知更清晰,project.pbxproj的总体布局如下所示:

project.pbxproj布局
  1. // !$*UTF8*$!
  2. {
  3.     archiveVersion = 1;
  4.     classes = {
  5.     };
  6.     objectVersion = 46;
  7.     objects = {
  8.     ...
  9.     }
  10.     rootObject = E6A557831C22979700A81AD5 /* Project object */;
  11. }
复制代码


  • 在project.pbxproj我们必要关注的是objects的内容,一般来说,工程越大越复杂,objects的内容就会越多。objects内里实际上是一个元素的Map, 每个Key用一个全文档唯一的uuid来表示。
objects中包含了多个Section, 也就是多种范例的信息。
  1. // !$*UTF8*$!
  2. {
  3.     archiveVersion = 1;
  4.     classes = {
  5.     };
  6.     objectVersion = 56;
  7.     objects = {
  8. /* Begin PBXBuildFile section */
  9.         XXXXXXXXXXXXXXXXXXXXXXXXXXX /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 880B73262AE53EFB00027A9F /* AppDelegate.m */; };
  10. /* End PBXBuildFile section */
  11. /* Begin PBXFileReference section */
  12. /* End PBXFileReference section */
  13. /* Begin PBXFrameworksBuildPhase section */
  14. /* End PBXFrameworksBuildPhase section */
  15. /* Begin PBXGroup section */
  16.         880B73192AE53EFB00027A9F = {
  17.             isa = PBXGroup;
  18.             children = (   
  19.                 XXXXXXXXXXXXXXXXXXXXXXXX* DEMO */,
  20.                 880B73232AE53EFB00027A9F /* Products */,
  21.             );
  22.             sourceTree = "<group>";
  23.         };
  24. /* End PBXGroup section */
  25. /* Begin PBXNativeTarget section */
  26.         880B73212AE53EFB00027A9F /* DEMO */ = {
  27.             isa = PBXNativeTarget;
  28.             buildConfigurationList = 880B733B2AE53EFC00027A9F /* Build configuration list for PBXNativeTarget "DEMO" */;
  29.             buildPhases = (
  30.                 880B731E2AE53EFB00027A9F /* Sources */,
  31.                 880B731F2AE53EFB00027A9F /* Frameworks */,   
  32.                 XXXXXXXXXXXXXXXXXXXXXXXX /* Resources */,
  33.             );
  34.             buildRules = (
  35.             );
  36.             dependencies = (
  37.             );
  38.             name = DEMO;
  39.             productName = DEMO;
  40.             productReference = 880B73222AE53EFB00027A9F /* DEMO.app */;
  41.             productType = "com.apple.product-type.application";
  42.         };
  43. /* End PBXNativeTarget section */
  44.     };
  45.     rootObject = 880B731A2AE53EFB00027A9F /* Project object */;
  46. }
复制代码

以上是obejcts的简化数据内容,它包含了许多我们在Xcode中经常会用到的配置内容
1.  PBXProject: 
    - 代表整个 Xcode 项目。
    - 包含项目标全局配置和设置,如项目名称、项目根目录、构建配置等。
    - 包含了项目中的全部 `PBXNativeTarget` 的列表。
2.  PBXNativeTarget:
    -   代表一个构建目标,可以是应用步调、库或其他可执行文件。
    -   包含了该目标的具体配置,如编译器选项、输出路径、依靠关系等。
3.  PBXFileReference:
    -   代表项目中的文件或文件夹。
    -   包含文件的路径、文件范例、引用等信息。
4.  PBXGroup:
    -   用于构造项目中的文件和文件夹,以创建项目标文件布局。
    -   可以包含 `PBXFileReference` 和其他 `PBXGroup`。
5.  PBXBuildFile:
    -  形貌编译阶段的文件引用,包括源文件(.m)和资源文件(xib大概storyboard).
6. PBXBuildPhase:
    - 形貌编译阶段. 是一个抽象概念,实际出现的是下面具体的项目;BuildPhase对应的是Xcode图形化界面上的Build Phase配置.
    - PBXCopyFilesBuildPhase: 拷贝文件阶段.PBXFrameworksBuildPhase: Framework编译阶段
    - PBXHeadersBuildPhase: 头文件编译阶段.
    - PBXResourcesBuildPhase: 资源文件拷贝编译阶段.
    - PBXShellScriptBuildPhase: 脚本执行阶段.
    - PBXSourcesBuildPhase: 源文件编译阶段.
7.  PBXContainerItemProxy:
    -   用于管理依靠关系和跨项目引用,通常在多项目工程中使用。
8.  XCBuildConfiguration:
    -   包含特定构建配置的设置,如编译器选项、链接选项等。
    -   `XCBuildConfiguration` 对象通常属于 `PBXNativeTarget`。
9.  XCConfigurationList:
    -   用于管理构建配置列表,每个 `PBXNativeTarget` 都有一个 `XCConfigurationList
这些内容在Xcode界面中有与之类似的配置项,定名也大多近似。针对这些Section修改可以完成Xcode配置项的修改,但必要注意将全部影响项一同修改完毕,否则很轻易就会导致工程文件错误。

5.2.3、脚本操作之增删改查

在我们脚本操作的第一步是旧SDK包体的删除和新的SDK包体的导入。这些文件的增删、配置的修改都是基于Target修改的,在project.pbxproj中我们修改的是PBXNativeTarget Section。
以下是PBXNativeTarget文件布局

PBXNativeTarget布局
  1. 880288D929013C8100802937 /* OneSDKDemo */ = {
  2.     isa = PBXNativeTarget;
  3.     buildConfigurationList = 880288F329013C8300802937 /* Build configuration list for PBXNativeTarget "OneSDKDemo" */;
  4.     buildPhases = (
  5.         880288D629013C8100802937 /* Sources */,
  6.         880288D729013C8100802937 /* Frameworks */,
  7.         880288D829013C8100802937 /* Resources */,
  8.     );
  9.     buildRules = (
  10.     );
  11.     dependencies = (
  12.     );
  13.     name = OneSDKDemo;
  14.     productName = OneSDKDemo_GSO;
  15.     productReference = 880288DA29013C8100802937 /* OneSDKDemo.app */;
  16.     productType = "com.apple.product-type.application";
  17. };
复制代码
以上面文件为例,要增删Framework,我们就要去修改UUID为880288D729013C8100802937的PBXFrameworksBuildPhase Section,而要增删bundle、图片等资源文件,我们就要修改UUID为880288D829013C8100802937的PBXResourcesBuildPhase。
以删除SDK为例,脚本会去遍历SDK文件夹内的全部内容,然后将其根据文件范例分别在差别的PBXBuildPhase中移除引用,随后删除文件。
必要注意的是:Unity游戏导出的工程有两个Target,代码挂载在UnityFramework Target上,图片等资源文件则是挂载在主Target上。我们在处理Unity工程的时间要区分Target操作。

删除SDK
  1. def delete_group(group)
  2.     group.files.each do |file|
  3.       if file.real_path.to_s.end_with?('.m', '.mm', '.cpp', '.h', '.swift')
  4.         @code_target.source_build_phase.remove_file_reference(file)
  5.         delete_path(file.real_path)
  6.         file.remove_from_project
  7.       elsif file.real_path.to_s.end_with?('.a') || file.real_path.to_s.end_with?('.framework')
  8.         @code_target.frameworks_build_phases.remove_file_reference(file)
  9.         delete_path(file.real_path)
  10.         file.remove_from_project
  11.       elsif file.real_path.to_s.end_with?('.plist', '.bundle')
  12.         @main_target.resources_build_phase.remove_file_reference(file)
  13.         delete_path(file.real_path)
  14.         file.remove_from_project
  15.       end
  16.     end
  17.     group.version_groups.each do |child|
  18.       if child.real_path.to_s.end_with?('.xcdatamodeld')
  19.         @main_target.resources_build_phase.remove_file_reference(child)
  20.         delete_path(child.real_path)
  21.         child.remove_from_project
  22.       else
  23.         delete_group(child, delete_files)
  24.       end
  25.     end
  26.     group.groups.each do |child|
  27.       delete_group(child)
  28.     end
  29.   end
复制代码
5.2.4、脚本操作之参数配置


游戏SDK所必要编辑的参数会合在Info.plist中,这里我们使用Ruby的Plist库来执行对plist文件的修改
Plist文件采用XML格式存储数据,这种格式可读性比project.pbxproj好多了,我们可以很清晰的知道必要修改文件层级和位置。
下面的代码我们演示了怎样在Xcode工程中添加权限形貌文案。这些权限和形貌文案来自游戏运营在发行平台上的配置,打包工具在打包时会获取最新的配置。

添加权限文案
  1. # 增加权限描述字符串
  2. def add_app_permissions(target_name, permissions)
  3.     return if permissions.nil?
  4.     plist_full_path = info_plist_path(target_name)
  5.     info = Plist.parse_xml(plist_full_path)
  6.     permissions.each do |key, value|
  7.         puts 'key : ', key, 'value:', value
  8.         info[key] = value
  9.     end
  10.     Plist::Emit.save_plist(info, plist_full_path)
  11. end
复制代码

在游戏的自动化出包流程中,打包脚本还有更多的工作,但大多都是使用Xcodeproj和Plist两个工具完成的工作。了解并把握project.pbxproj的内容和含义,并使用Xcodeproj和Plist对其编辑修改,就可以完成绝大多数Xcode工程修改的工作。

5.2.5、打包工具概览




在整体设计上,打包工具结合游戏发行系统,获取游戏维度的发行计划,研发无需感知游戏SDK所必要配置的参数。
同时打包工具将SDK版本的接入管理归拢至打包工具中,可以根据游戏的运营状态而差别化下发接入SDK的版本。



打包工具在使用上也很简朴,游戏研发在登录游戏发行账号后,只必要完成三步配置即可快速完成发行包的接入。
未来后续打包工具会纳入更多契合业务模式的功能,例如接入合规检测、SDK功能自检等功能,持续为游戏的开辟提效。

6、未来规划


当前,OneSDK已交付给游戏使用,研发必要接入的SDK从最少2个减少至最多1个。打包工具将在年内上线供研发使用,在结合使用OneSDK和打包工具的情况下,预计可以资助游戏减少60%的接入耗时。
提高效率是一个不绝迭代的过程,未来,我们会站在全球发行的角度,不绝完满和丰富OneSDK和打包工具,简化游戏的接入步调,同时提供更多有用的工具资助研发提拔效率。

参考文献:
https://www.rubydoc.info/gems/xcodeproj
https://github.com/patsplat/plist
https://muhuashanjin.github.io/2017/10/09/2017-10-09-Project.pbxproj/


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表