Unity导出iOS工程后Xcode构建因Vuforia相关重复任务失败
我碰到过不少开发者在Unity结合Vuforia导出iOS工程后,用Xcode 15构建时遇到这个「重复任务」的报错,确实挺影响效率的,尤其是自动化构建场景下。
问题详情
从Unity导出iOS工程后,Xcode立即报**"Unexpected duplicate tasks"**错误,具体是Unity-iPhone目标存在两条完全一致的UnityDriver.framework复制命令:
Target 'Unity-iPhone' (project 'Unity-iPhone') has copy command from '/Users/michael/vc/XXX/Builds/iOS/XXXXcode/Frameworks/com.ptc.vuforia.engine/Vuforia/Plugins/iOS/UnityDriver.framework' to '/Users/michael/Library/Developer/Xcode/DerivedData/Unity-iPhone-eviafjkjongbbigjhjevcxprpjsg/Build/Products/ReleaseForRunning-iphoneos/XXX.app/Frameworks/UnityDriver.framework'
这条错误会重复出现两次,本质是Vuforia的导出逻辑在Xcode工程里生成了重复的「Embed Framework」构建步骤。
临时手动解决办法
你提到的手动删除Build Phases里重复的「Embed Framework」步骤确实能解决问题,但显然不适用于自动化构建流水线,我们需要更高效的方案。
适配自动化构建的解决方案
1. Unity PostProcessBuild 脚本自动修复
最可靠的方式是在Unity导出阶段就自动处理这个问题,写一个简单的编辑器脚本,放在Unity项目的Assets/Editor文件夹下,导出iOS工程时会自动清理重复的框架嵌入任务:
using UnityEditor; using UnityEditor.Callbacks; using UnityEngine; using UnityEditor.iOS.Xcode; public class FixVuforiaDuplicateFrameworkEmbed { [PostProcessBuild(999)] // 确保在其他PostProcess脚本之后执行 public static void OnPostProcessBuild(BuildTarget target, string pathToBuiltProject) { if (target != BuildTarget.iOS) return; // 读取Xcode工程文件 string projectPath = $"{pathToBuiltProject}/Unity-iPhone.xcodeproj/project.pbxproj"; PBXProject pbxProject = new PBXProject(); pbxProject.ReadFromFile(projectPath); string mainTargetGuid = pbxProject.GetUnityMainTargetGuid(); string targetFrameworkPath = "Frameworks/com.ptc.vuforia.engine/Vuforia/Plugins/iOS/UnityDriver.framework"; // 获取Embed Frameworks构建阶段 var embedPhase = pbxProject.GetBuildPhaseByType(mainTargetGuid, PBXProject.GetPBXBuildPhaseType("Embed Frameworks")); if (embedPhase == null) return; // 追踪已处理的框架路径,移除重复项 var processedPaths = new System.Collections.Generic.HashSet<string>(); var duplicateFileGuids = new System.Collections.Generic.List<string>(); foreach (var fileGuid in embedPhase.files) { string filePath = pbxProject.GetFileDisplayName(fileGuid); if (filePath.Equals(targetFrameworkPath)) { if (processedPaths.Contains(filePath)) { duplicateFileGuids.Add(fileGuid); } else { processedPaths.Add(filePath); } } } // 删除重复的条目 foreach (var guid in duplicateFileGuids) { pbxProject.RemoveFileFromBuildSection(mainTargetGuid, embedPhase.guid, guid); } // 保存修改后的工程文件 pbxProject.WriteToFile(projectPath); } }
这个脚本会在Unity导出完成后自动检查并移除重复的UnityDriver.framework嵌入任务,完全不需要手动干预,完美适配CI/CD流水线。
2. 检查版本兼容性并等待官方修复
目前你使用的版本组合:Unity 2022.3.14f1 + Vuforia 10.19.3 + Xcode 15.0.1,可能存在版本适配问题。Xcode 15对框架嵌入的逻辑有一些调整,Vuforia后续版本可能会修复这个导出时的重复任务bug,可以关注Vuforia的官方更新日志,一旦有适配Xcode 15的补丁发布,升级后应该能彻底解决问题。
3. 自动化构建工具中添加预处理步骤
如果你的流水线是用Fastlane、Jenkins等工具搭建的,也可以在Xcode构建前加一个脚本步骤,直接修改Xcode工程文件移除重复条目。比如用Fastlane的话,可以在Fastfile里添加:
lane :build_ios do # 导出Unity工程的步骤... # 修复重复框架嵌入 sh "sed -i '' '/UnityDriver.framework.*Embed/d' Unity-iPhone.xcodeproj/project.pbxproj" # 后续Xcode构建步骤... end
不过这种方式依赖pbxproj文件的格式,稳定性不如Unity编辑器脚本,适合临时过渡使用。
总结
优先推荐使用Unity的PostProcessBuild脚本,从源头解决问题;同时关注Vuforia的版本更新,等待官方修复这个适配Xcode 15的bug。这样不管是本地开发还是自动化构建,都能避开这个报错。
备注:内容来源于stack exchange,提问作者MichaelC

