Version: 2022.1
Inside the iOS build process
Getting started with iOS

Unity Xcode 项目的结构

为 iOS 平台构建 Unity 项目时,Unity 将创建一个包含 Xcode 项目的文件夹。为了在将应用程序部署到设备上之前对此应用程序进行编译和签名,您需要该项目。此外,还需要使用该项目来准备和捆绑游戏,以便分发到 App Store 上。自 Unity 2019.3 起,Xcode 项目结构已更改,旨在支持通过 Unity 用作库将 Unity 集成到原生 iOS 应用程序中。

Before you build your Project for iOS, make sure that you set the Bundle Identifier in the iOS Player Settings (menu: Edit > Project Settings > Player Settings). You can also choose whether your app targets the simulator or an actual device. To do this, change the SDK version field.

项目目标

每个生成的 Unity iOS Xcode 项目都具有以下结构和目标:

  • UnityFrameworkUnityFramework 目标中的一个库部分。此部分包括 ClassesUnityFrameworkLibraries 文件夹,以及相关的框架。另外,Xcode 将此部分用于构建 UnityFramework.framework 文件。
  • Unity-iPhoneUnity-iPhone 目标中的一个瘦启动器部分。此部分包括 MainApp 文件夹和应用程序表现数据(例如启动屏幕、.xib 文件、图标、数据和 /Info.plist 文件),并可运行该库。Unity-iPhone 目标对 UnityFramework 目标具有单一依赖关系。

Classes 文件夹

Classes 文件夹包含用于集成 Unity Runtime 和 Objective-C 的代码。Unity 将应用程序的入口点存储在此文件夹内的 main.mmUnityAppController.mm/h 文件中。您可以自行创建派生自 UnityAppController 的 AppDelegate,或者如果您的任何插件包含 AppController.h_,则您可以改为包含 UnityAppController.h。如果 Plugins/iOS_ 文件夹包含 _AppController.mm/h_,可以对它们进行合并和重命名。

InternalProfiler.h 文件还定义一个条件编译器来启用内部性能分析器。此文件夹中的代码不会经常更改,您可以在此处放置自定义类。如果您选择 Append 模式,Xcode 会在不同构建中保留对此文件夹的更改。但是,此功能不支持多个构建目标,并且需要固定结构的 Libraries 文件夹。

Unity 的内部性能分析器具有快速且不易察觉的特点,并提供以下相关基本信息:

  • 哪个子系统占用最多的帧时间。
  • .NET 堆大小。
  • GC 事件计数和持续时间。

有关更多信息,请参阅内置性能分析器的相关文档。

Data 文件夹

此文件夹包含应用程序的序列化资源以及 .NET 程序集(.dll 或 .dat 文件),其形式为完整代码或元数据(取决于代码剥离设置)。machine.config 文件可以设置各种 .NET 服务(例如安全性和 WebRequest)。Xcode 在每次构建时都会刷新此文件夹的内容。您不应对其进行任何更改。

默认情况下,_Data_ 文件夹的 Target Membership 设置为 Unity-iPhone 目标,并且 Unity Runtime 会在 mainBundle 中搜索该文件夹。要更改 Unity Runtime 用于查找 Data 文件夹的默认捆绑包,请在 UnityFramework 实例上调用 setDataBundleId: "com.my.product",然后调用运行函数之一。例如,如果您希望拥有 Data 以及 UnityFramework 调用,请使用 setDataBundleId: "com.unity3d.framework" 并将 Target Membership 设置为 UnityFramework

注意:仅当 Data 文件夹是应用程序目标的一部分而不是 UnityFramework 目标的一部分时,才支持按需加载资源 (On-Demand Resources)。

Libraries 文件夹

Libraries 文件夹包含用于 IL2CPP 的 libil2cpp.alibiPhone-lib.a 文件是 Unity Runtime 静态库,_RegisterMonoModules.cpp_ 将 Unity 原生代码与 .NET 绑定。Xcode 在每次构建时都会刷新此文件夹的内容。您不应对其进行任何更改。

自定义文件夹

您可以将自定义文件放置于此。

图形文件

图标和启动画面(.png 文件)位于 Unity-iPhone 文件夹中的资源目录中。Unity 自动管理这些文件。启动屏幕、它们的 XML 接口构建器(.xib 文件)和 Storyboard 文件存储在项目的根文件夹中。要在 Unity 中设置它们,请使用 Player Settings 窗口(菜单:Edit > Project Settings > Player Settings)。创建自定义启动图像时,请确保图像遵守 Apple 的人机接口指南

属性列表 (.plist) 文件

可从 Unity 的 Player Settings(菜单:Edit > Project Settings > Player Settings,然后选择 Other 部分并向下滚动到 Identification 部分;有关更多详细信息,请参阅 iOS Player 设置 - Identification 的相关文档)中管理 Unity-iPhone 目标内的 /Info.plist 文件(通过 mainBundle 进行访问)。Unity 在构建播放器时会更新此文件,而不是进行替换。除非迫不得已,否则不要对其进行更改。

/UnityFramework/Info.plist 文件(通过 bundleWithIdentifier:@"com.unity3d.framework" 进行访问)是 UnityFramework 的一部分。您可以将一些值保留在此处,而不是 mainBundle 的 /Info.plist 文件中,这样能确保如果将 UnityFramework 移至另一个应用程序中,您仍然可以获取这些值。

其他文件

这些文件包括 Xcode 项目文件(.xcodeproj 文件)以及仅在 Project Navigator 中显示的框架链接。

通过 xcodebuild 构建 Xcode 项目

使用命令行参数来指定构建设置时,这些设置会影响所有 Xcode 项目目标。为了防止发生这种情况,某些构建设置具有后缀版本。您可以使用这些后缀版本来指定构建设置影响的目标。这是通过用户定义的设置来实现的(*APP 后缀用于应用程序目标,*FRAMEWORK 后缀用于框架目标)。

使用 xcodebuild 进行构建时,请将后缀版本用于:

PRODUCT_NAME -> PRODUCT_NAME_APP

PROVISIONING_PROFILE -> PROVISIONING_PROFILE_APP

PROVISIONING_PROFILE_SPECIFIER -> PROVISIONING_PROFILE_SPECIFIER_APP

OTHER_LDFLAGS -> OTHER_LDFLAGS_FRAMEWORK

根据您的自定义构建管线,您可以扩展此列表以涵盖其他设置。

修改 Xcode 项目

要修改生成的 Xcode 项目,请使用 Xcode.PBXProject

项目目标

从 Unity 2019.3 开始,已弃用 PBXProject.GetUnityTargetNamepbxProject->TargetGuidByName("Unity-iPhone")。接下来可以改用 pbxProject->GetUnityFrameworkTargetGuid()pbxProject->GetUnityMainTargetGuid()

// 已弃用
string targetGuid = proj.TargetGuidByName("Unity-iPhone");
string targetGuid = proj.TargetGuidByName(PBXProject.GetUnityTargetName());

// 改为以下调用之一
string targetGuid = proj.GetUnityFrameworkTargetGuid(); 
string targetGuid = proj.GetUnityMainTargetGuid();

如果需要在包或自定义构建后处理器中同时支持新旧代码路径,请遵循以下步骤:

1.尽可能依靠插件导入器功能(例如,用于指定其他框架)。 2.使用反射:

string mainTargetGuid;
string unityFrameworkTargetGuid;
        
var unityMainTargetGuidMethod = proj.GetType().GetMethod("GetUnityMainTargetGuid");
var unityFrameworkTargetGuidMethod = proj.GetType().GetMethod("GetUnityFrameworkTargetGuid");
                
if (unityMainTargetGuidMethod != null && unityFrameworkTargetGuidMethod != null)
{
    mainTargetGuid = (string)unityMainTargetGuidMethod.Invoke(proj, null);
    unityFrameworkTargetGuid = (string)unityFrameworkTargetGuidMethod.Invoke(proj, null);
}
else
{
    mainTargetGuid = proj.TargetGuidByName ("Unity-iPhone");
    unityFrameworkTargetGuid = mainTargetGuid;
}
  • 2019.3 中添加了“Unity 用作 iOS 库”。NewIn20193
Inside the iOS build process
Getting started with iOS