Unity通过PBXProject生成XCode工程
Unity版本:2020.3.47f1
首先通过PostProcessBuildAttribute监听XCode工程导出完成事件,GetUnityMainTargetGuid是获取XCode工程中"Unity-iPhone"对应的target,GetUnityFrameworkTargetGuid则对应"UnityFramework",在unity中大部分操作会是针对UnityFramework。PBXProject的很多操作都是通过guid的,下面会出现各种各样的guid。
下面是基础代码:
static PBXProject pbxProject; static string mainTarget; static string frameworkTarget; [PostProcessBuildAttribute] public static void OnPostprocessBuild(BuildTarget buildTarget, string path) { if (buildTarget == BuildTarget.iOS) {
string pbxProjectPath = PBXProject.GetPBXProjectPath(path); pbxProject = new PBXProject(); pbxProject.ReadFromString(File.ReadAllText(pbxProjectPath)); mainTarget = pbxProject.GetUnityMainTargetGuid();//这个对应target中的Unity-iPhone frameworkTarget = pbxProject.GetUnityFrameworkTargetGuid();//这个对应target中UnityFramework //...
//你的操作
//...
pbxProject.WriteToFile(pbxProjectPath); //操作完后要写回文件,否则无效 } }
一、BuildSettings
使用SetBuildProperty设置BuildSettings中的设置,参数分别为target、设置名、设置值,其中设置名可以参考这里,比如:
pbxProject.SetBuildProperty(mainTarget, "ENABLE_BITCODE", "NO"); pbxProject.SetBuildProperty(frameworkTarget, "ENABLE_BITCODE", "NO");
如果需要对Debug、Release分别设置,使用BuildConfigByName和SetBuildPropertyForConfig即可,比如:
string debugConfig = pbxProject.BuildConfigByName(mainTarget, "Debug");//Debug、Release、ReleaseForProfiling、ReleaseForRunning pbxProject.SetBuildPropertyForConfig(debugConfig , "ENABLE_BITCODE", "NO");
BuildSettings中的所有设置都可以通过上面两个方法设置,包括签名等设置,签名后面单独写。
二、BuildPhases
1、加入至CopyBundleResources
使用AddFile和AddFileToBuild,如下代码,GoogleService-Info.plist与Unity-iPhone.xcodeproj在同一级目录下,下面代码只加到了mainTarget中,如有需要也可加入frameworkTarget
string filePath = "GoogleService-Info.plist"; string fileGuid = pbxProject.AddFile(filePath, filePath, PBXSourceTree.Source); pbxProject.AddFileToBuild(mainTarget, fileGuid);
2、加入至CompileSources
代码都需要加入到这里,注:AppleLogin.m在Apple目录中,Apple与Unity-iPhone.xcodeproj在同一级目录,不需要对Apple文件夹做任何操作,不要使用"Apple/AppleLogin.m",否则会找不着路径,必须使用Path.Combine。
string filePath = Path.Combine("Apple", "AppleLogin.m"); string fileGuid = pbxProject.AddFile(filePath, filePath, PBXSourceTree.Source); var sourcesBuildPhase = pbxProject.GetSourcesBuildPhaseByTarget(mainTarget); pbxProject.AddFileToBuildSection(target, sourcesBuildPhase, fileGuid);
3、LinkBinaryWithLibraries
这块会比较复杂,要分开为4种情况
·系统Framework
使用AddFrameworkToProject,函数很简单,三个参数分别是target、framework名、是否为弱引用,framework名必须以".framework"结尾,弱引用为false时对应xcode中的Required
pbxProject.AddFrameworkToProject(frameworkTarget, "AdSupport.framework", false);
·SwiftPackageManager中的Framework
当工程中用到了SwiftPakcageManager则需要调用以下方法,如下面用到的是Firebase包中的三个framework,Remote相关接口是在Unity2020.3.42新加的,具体可查看官方文档。其中AddRemotePackageFrameworkToProject既是添加到LinkBinaryWithLibraries中,framework的名字不带任何后缀
string firebaseGuid = pbxProject.AddRemotePackageReferenceAtVersion("https://github.com/firebase/firebase-ios-sdk", "10.8.1"); pbxProject.AddRemotePackageFrameworkToProject(frameworkTarget, "FirebaseMessaging", firebaseGuid, false); pbxProject.AddRemotePackageFrameworkToProject(frameworkTarget, "FirebaseAnalytics", firebaseGuid, false); pbxProject.AddRemotePackageFrameworkToProject(frameworkTarget, "FirebaseCrashlytics", firebaseGuid, false);
·target作为Framework
由于前面的remoteFramework全部是添加至frameworkTarget中,mainTarget中的代码可能会报错,如果mainTarget中也添加一次,会报两个target中有重复代码的提示,但依然可以编译通过,运行时会有比较诡异的情况发生,比如FirebaseCloudMessaging中的注册token会每次启动都更新,解决方法是把UnityFramework添加至Unity-iPhone的LinkBinaryWithLibraries中,代码如下:
string file = "UnityFramework.framework"; string fileGuid = pbxProject.AddFile(file, file, PBXSourceTree.Build); if (fileGuid != null) { var sourcesBuildPhase = pbxProject.GetFrameworksBuildPhaseByTarget(mainTarget); pbxProject.AddFileToBuildSection(mainTarget, sourcesBuildPhase, fileGuid); }
·本地Framework
本地Framework也有点特殊,调用的是AddFileToBuild,注:FBAudienceNetwork.framework在sdks目录中,sdks与Unity-iPhone.xcodeproj同一级,不需要单独添加sdks这个目录,否则会找不着所添加的framework
string filePath = Path.Combine("sdks", "FBAudienceNetwork.framework"); string fileGuid = pbxProject.AddFile(filePath, filePath, PBXSourceTree.Source); pbxProject.AddFileToBuild(frameworkTarget, fileGuid);
三、Info.plist
Info.plist比较简单,修改OnPostprocessBuid方法,新加如info.plist读取
static PBXProject pbxProject; static string mainTarget; static string frameworkTarget; static PlistDocument plist; [PostProcessBuildAttribute] public static void OnPostprocessBuild(BuildTarget buildTarget, string path) { if (buildTarget == BuildTarget.iOS) { string pbxProjectPath = PBXProject.GetPBXProjectPath(path); pbxProject = new PBXProject(); pbxProject.ReadFromString(File.ReadAllText(pbxProjectPath)); mainTarget = pbxProject.GetUnityMainTargetGuid();//这个对应target中的Unity-iPhone frameworkTarget = pbxProject.GetUnityFrameworkTargetGuid();//这个对应target中UnityFramework string plistPath = xcodeProjectPath + "/Info.plist"; plist = new PlistDocument(); plist.ReadFromString(File.ReadAllText(plistPath)); //... //你的操作 //... pbxProject.WriteToFile(pbxProjectPath); //操作完后要写回文件,否则无效 plist.WriteToFile(plistPath);//plist也要写回文件 } }
plist的修改需要结合文件本身的结构,推荐先在xcode中操作后,看plist中结构是怎么样的,再利用unity提供的接口进行修改
四、Capabilities待续
五、签名待续
六、其他
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Ollama——大语言模型本地部署的极速利器
· 使用C#创建一个MCP客户端
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· Windows编程----内核对象竟然如此简单?
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用