Version: 2019.4
iOS 构建过程详解
自定义 iOS 启动画面

Unity Xcode 项目的结构

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

构建 iOS 项目之前,务必在 iOS Player Settings****(菜单:Edit > Project Settings > Player Settings)中设置 Bundle Identifier。还可以选择应用程序的目标是模拟器还是实际设备。为此,请更改 SDK version 字段。

项目目标

每个生成的 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
iOS 构建过程详解
自定义 iOS 启动画面