UnityIOS打包自动化——PBXProject使用经验
一、概述
PBXProject是Unity官方提供的一组对XCode工程配置文件project.pbxproj的增删改查接口。结合OnPostprocessBuild方法,可以在Unity打包出XCode工程后,通过代码对XCode工程进行设置。常用的有添加库,修改BuildSettings,修改info.plist等功能,这部分基础功能网上资料比较多,这里就不赘述了。
本篇分享主要是记录一下使用PBXProject设置XCode中一些特殊选项的思路,按照此方法,理论上可以将所有XCode工程中的操作用代码自动实现。
二、需求背景
本次分享主要是针对一个比较特殊的需求展开,Unity 2019.3.a2版本之后IOS新增了将Unity工程打包成.framework库添加到其他项目中的功能(把小游戏打包成库加入其他项目中用于马甲包提审)。我想要实现打包后自动对XCode工程进行设置,需求如下:
Unity资源文件的Target Membership设置默认都是不勾选UnityFramework的,需要用代码将UnityFramework勾选上。
三、落地
1.知识储备
首先对project.pbxproj文件的格式得有个基本认知,最外层的结构如下,是一种类似Json的存储格式,使用 UUID作为索引 (可以当作Unity中Assets的GUID去理解,总之就是资源根据某些规则生成的唯一索引), 保证每个配置信息对象的唯一性。
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
};
rootObject = xxxxxx /* Project object */;
}
主要配置内容存储在objects中,详情下面的链接整理得非常细了,下文只举例用例中用到一部分。
Xcode工程文件的格式说明
2.分析需求
我们的需求本质上是用代码修改配置文件,达到和使用XCode的GUI勾选一样的效果。而具体要修改哪里,实践出真知,最简单的方法就是在XCode编辑器中,勾选我们需要的选项,然后对比配置文件前后发生的变化。
- 通过对比,发现Data目录勾选UnityFramework选项后配置文件发生的变化是在PBXResourcesBuildPhase Section中,有三个Resources数据块,其中之一的files列表,增加了Data文件夹对应的UUID 。(以下UUID都以伪代码的形式表示 实际上是一串无规律的字符串)
/*Begin PBXResourcesBuildPhase section */
Resources的UUID /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
Data文件夹的UUID /* Data in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
//同结构不同UUID的结构还有两个 这里省略了
/*End PBXResourcesBuildPhase section */
- 继续搜索Resources的UUID发现在UnityFramework的buildPhases中出现
UnityFramework的UUID /* UnityFramework*/ = {
isa = PBXNativeTarget;
buildConfigurationList = C01FCF4A08A954540054247B
/* Build configuration list for PBXNativeTarget "UnityFramework" */;
buildPhases = (
xxxxxxxxxxxxxxxxxxxxxxxx/* Sources */,
xxxxxxxxxxxxxxxxxxxxxxxx/* Frameworks*/,
xxxxxxxxxxxxxxxxxxxxxxxx/* Headers*/,
xxxxxxxxxxxxxxxxxxxxxxxx/* ShellScript*/,
Resources的UUID/* Resources */,
);
//省略了不相关的部分
}
- 再继续搜UnityFramework的UUID发现能在targets中找到
//省略了很多
projectRoot = "",
targets = {
Unity-iPhone的UUID /*"Unity-iPhone" */
Unity-iPhone Test的UUID /*"Unity-iPhone Test" */
UnityFramework的UUID /*"UnityFramework" */
}
- 至此欣喜的发现同级的是我们熟悉的Unity-iPhone和Unity-iPhone Tests
3.实现
经过上面的分析我们的层级关系和要做的事就很明朗了
在XCode 操作GUI勾选Target Membership等价于在project.pbxproj配置文件中的
UnityFramework/Resources/PBXResourcesBuildPhase Section/files列表加入所需文件或文件夹的UUID
查一查API(官方这块的文档写得比较随意,翻了PBXProject源码才找到),以“Data”文件夹举例,最后实现如下:
//获取UnityFramework的UUID
frameTarget = project.GetUnityFrameworkTargetGuid();
//获取UnityFramework下的PBXResourcesBuildPhase Section UUID
string resourceTarget = project.GetResourcesBuildPhaseByTarget(frameTarget);
//根据Data目录相对路径获取UUID
resGUID = project.FindFileGuidByProjectPath("Data");
//添加Data UUID进file目录
project.AddFileToBuildSection(frameTarget, resourceTarget, resGUID);
四、总结
Mac系统的操作和自动化的实现相对没那么熟悉,所以选择在更容易上手的C#侧尽可能多的完成自动化的步骤,PBXProject可以作为IOS打包发版自动化流程中的一环,使用C#实现且开源,还是值得学习了解的。