自学内容网 自学内容网

【Unity高级】一文了解Unity 中的条件编译(附所有指令)

在这里插入图片描述

一、Unity中的条件编译

Unity 对 C# 语言的支持包括使用指令,这些指令允许您根据是否定义了某些脚本符号,选择性地包含或排除代码的编译。有关这些指令在 C# 中如何工作的更多信息,请参阅微软关于 C# 预处理器指令 的文档。

(一)预定义符号

Unity 提供了一系列预定义的符号,您可以在脚本中使用它们,选择性地包含或排除代码段的编译。例如,在 Windows 独立平台的项目构建中定义的符号是 UNITY_STANDALONE_WIN。您可以使用一种特殊类型的 if 语句检查此符号是否已定义:

#if UNITY_STANDALONE_WIN
    Debug.Log("Standalone Windows");
#endif

#if#endif 前的井号(#)表示这些语句是编译过程中处理的指令,而不是在运行时处理的指令。在上述示例中,Debug 行仅在项目的 Windows 独立构建中包含在编译中。在 Unity 编辑器或其他目标构建中编译时,它会被完全省略。这与使用常规的 if 语句不同,后者可能仅在运行时绕过某些代码段的执行。

(二)多条件检查

您可以使用 #elif#else 指令来检查多个条件:

#if UNITY_EDITOR
    Debug.Log("Unity Editor");
#elif UNITY_IOS
    Debug.Log("Unity iOS");
#else
    Debug.Log("Any other platform");
#endif

(三)预定义符号的作用范围

Unity 有多个预定义符号,允许您根据所选平台、编辑器版本和其他系统环境场景,选择性地编译或省略代码。

二、Unity 脚本符号参考

(一)平台符号

Unity 根据创作和构建目标平台自动定义某些符号,具体如下:

定义功能
UNITY_EDITOR用于在游戏代码中调用 Unity 编辑器脚本的脚本符号。
UNITY_EDITOR_WIN用于 Windows 上编辑器代码的脚本符号。
UNITY_EDITOR_OSX用于 macOS 上编辑器代码的脚本符号。
UNITY_EDITOR_LINUX用于 Linux 上编辑器代码的脚本符号。
UNITY_EMBEDDED_LINUX用于嵌入式 Linux 的脚本符号。
UNITY_QNX用于 QNX 的脚本符号。
UNITY_STANDALONE_OSX用于专门为 macOS(包括 Universal、PPC 和 Intel 架构)编译或执行代码的脚本符号。
UNITY_STANDALONE_WIN用于专门为 Windows 独立应用程序编译/执行代码的脚本符号。
UNITY_STANDALONE_LINUX用于专门为 Linux 独立应用程序编译/执行代码的脚本符号。
UNITY_STANDALONE用于为任何独立平台(Mac OS X、Windows 或 Linux)编译/执行代码的脚本符号。
UNITY_SERVER用于为专用服务器(macOS、Windows 或 Linux)编译/执行代码的脚本符号。
UNITY_IOS用于为 iOS 平台编译/执行代码的脚本符号。
UNITY_ANDROID用于 Android 平台的脚本符号。
UNITY_TVOS用于 Apple TV 平台的脚本符号。
UNITY_VISIONOS用于 VisionOS 平台的脚本符号。
UNITY_WSA用于通用 Windows 平台的脚本符号。
UNITY_WSA_10_0用于通用 Windows 平台的脚本符号。
UNITY_WEBGL用于 Web 的脚本符号。
UNITY_ANALYTICS用于在游戏代码中调用 Unity Analytics 方法的脚本符号。
UNITY_ASSERTIONS用于断言控制流程的脚本符号。
UNITY_64用于 64 位平台的脚本符号。 实际上不建议使用,因为它在所有 64 位架构上并不适用,且同一平台上的不同 CPU 架构可能共享相同的编译程序集。要基于架构条件执行代码,请使用标准的 if 语句检查 IntPtr.Size,在 32 位进程中为 4,64 位进程中为 8。示例请参阅“指令的替代方案”。

(二)Unity 编辑器版本符号

Unity 根据您当前使用的 Unity 编辑器版本自动定义某些脚本符号。

假设版本号为 X.Y.Z(例如 2019.4.14),Unity 以以下格式暴露三个全局脚本符号:UNITY_XUNITY_X_YUNITY_X_Y_Z

以下是 Unity 2019.4.14 中暴露的脚本符号示例:

定义功能
UNITY_2019用于 Unity 2019 发行版本的脚本符号,在每个 2019.Y.Z 版本中均可见。
UNITY_2019_4用于 Unity 2019.4 主要版本的脚本符号,在每个 2019.4.Z 版本中均可见。
UNITY_2019_4_14用于 Unity 2019.4.14 次要版本的脚本符号。

您还可以基于编译或执行代码段所需的最早 Unity 版本有选择地编译代码。按照上述相同的版本格式(X.Y),Unity 以 UNITY_X_Y_OR_NEWER 的格式暴露一个全局 #define,您可以使用它来实现此目的。

(三)其他符号

Unity 定义的其他符号包括:

定义功能
CSHARP_7_3_OR_NEWER当使用支持 C# 7.3 或更高版本的编译脚本时定义。
ENABLE_MONOMono 的脚本后端 #define
ENABLE_IL2CPPIL2CPP 的脚本后端 #define
ENABLE_VR当目标构建平台支持 VR 时定义。 注意:这并不意味着当前启用了 VR 或安装了支持 VR 所需的插件和包。
NET_2_0当在 Mono 和 IL2CPP 上针对 .NET 2.0 API 兼容级别构建脚本时定义。
NET_2_0_SUBSET当在 Mono 和 IL2CPP 上针对 .NET 2.0 子集 API 兼容级别构建脚本时定义。
NET_LEGACY当在 Mono 和 IL2CPP 上针对 .NET 2.0 或 .NET 2.0 子集 API 兼容级别构建脚本时定义。
NET_4_6当在 Mono 和 IL2CPP 上针对 .NET 4.x API 兼容级别构建脚本时定义。
NET_STANDARD_2_0当在 Mono 和 IL2CPP 上针对 .NET Standard 2.0 API 兼容级别构建脚本时定义。
NET_STANDARD_2_1当在 Mono 和 IL2CPP 上针对 .NET Standard 2.1 API 兼容级别构建脚本时定义。
NET_STANDARD当在 Mono 和 IL2CPP 上针对 .NET Standard 2.1 API 兼容级别构建脚本时定义。
NETSTANDARD2_1当在 Mono 和 IL2CPP 上针对 .NET Standard 2.1 API 兼容级别构建脚本时定义。
ENABLE_WINMD_SUPPORT当在 IL2CPP 上启用 Windows Runtime 支持时定义。有关详细信息,请参阅Windows Runtime 支持。
ENABLE_INPUT_SYSTEM当在播放器设置中启用输入系统包时定义。
ENABLE_LEGACY_INPUT_MANAGER当在播放器设置中启用传统输入管理器时定义。
DEVELOPMENT_BUILD当您的脚本在启用了开发构建选项的播放器中运行时定义。 注意:此定义仅反映构建时是否启用了开发构建选项。要确定您的脚本是否正在以开发构建模式运行,请使用 Debug.isDebugBuild__DEVELOPMENT_BUILD__ 并不足以确定当前是否正在以开发构建运行,因为大多数平台允许在不重新构建项目的情况下在开发和非开发构建之间切换。然而,在某些平台上,Unity 不支持在编辑器中切换开发和非开发构建,需要在构建完成后进行切换。例如,在 Windows 上,您可以选择“创建 Visual Studio 解决方案”选项,以选择是否在 Visual Studio 中进行开发或非开发构建。Visual Studio 中的切换不会重新编译您的脚本,因此不会重新评估脚本定义。您还可以通过将游戏构建中的 UnityPlayer.dll 与开发构建中的 UnityPlayer.dll 互换,来从最终的游戏构建切换到开发构建,以调试实时游戏构建。
UNITY_CLOUD_BUILD当项目使用 Unity 构建自动化构建时定义。

注意DEBUG 符号在 C# 和 Unity 中是预定义的,使用指令 #if DEBUG 等同于 #if UNITY_EDITOR || DEVELOPMENT_BUILD

三、自定义脚本符号

除了 Unity 内置的脚本符号外,您还可以定义自己的自定义脚本符号。定义自定义脚本符号的位置决定了它们的适用范围。您可以在以下位置定义自定义符号:

  • 资产文件,适用于项目中所有编辑器和播放器代码的符号,无论活动的构建配置文件是什么。
  • 平台配置,适用于当特定平台或其构建配置文件处于活动状态时的所有编辑器和播放器代码的符号。
  • 构建配置文件,适用于当特定构建配置文件处于活动状态时的所有编辑器和播放器代码的符号。
  • 代码中,适用于活动平台或单个播放器构建,具体取决于使用的 API。

(一)适用于整个项目的自定义符号

您可以通过响应文件资产为整个项目定义自定义脚本符号,方法如下:

  1. 将文件命名为 csc.rsp 并将其放置在项目的 Assets 文件夹根目录中。
  2. 在以 -define: 开头的行中定义脚本符号,后跟一个或多个用分号分隔的脚本符号。
  3. Unity 会在启动时读取此文件,并在编译任何代码之前应用它。例如,如果在 csc.rsp 文件中包含单行 -define:UNITY_DEBUG;UNITY_TEST,则符号 UNITY_DEBUGUNITY_TEST 将作为全局定义的脚本符号包含在项目中的所有 C# 脚本中。

注意:对 .rsp 文件的更改在 Unity 重新编译脚本之前不会生效。您可以通过更新或重新导入单个脚本文件来触发重新编译。

(二)适用于特定平台的自定义符号

您可以通过以下步骤为特定平台定义自定义脚本符号:

  1. 打开 Player Setting
  2. 导航到 Other Settings > Script Compilation 部分中的 Script Define Symbols
  3. 通过选择 + 按钮并在文本字段中输入符号名称,将新的脚本符号添加到列表中。使用 - 按钮删除现有列表项。
  4. 编辑完成后,选择 Apply 以应用更改。Unity 会使用新的符号重新编译项目中的脚本。

在这里插入图片描述

注意复制定义 按钮会将当前自定义脚本符号列表中的符号作为分号分隔的字符串复制到剪贴板。

(三)适用于构建配置文件的自定义符号

您可以通过以下步骤为构建配置文件定义自定义脚本符号:

  1. Build Profile 窗口中选择要为其定义符号的构建配置文件。
  2. 导航到 Build Data 部分中的 Scripting Defines。(只有在自定义的Build Profile中才能看到)。
  3. 通过选择 + 按钮并在文本字段中输入符号名称,将新的脚本符号添加到列表中。使用 - 按钮删除现有列表项。对列表的修改会自动保存和应用。

在这里插入图片描述

注意:您可以使用 -activeBuildProfile 命令行参数启动编辑器,以使指定的构建配置文件及其自定义脚本符号从启动时即生效。

(四)从代码中定义自定义符号

您可以使用以下 API 来定义脚本符号:

  • PlayerSettings.SetScriptingDefineSymbols
  • BuildPlayerOptions.extraScriptingDefines
  • Build.Player.ScriptCompilationSettings.extraScriptingDefines

BuildPlayerOptions.extraScriptingDefinesBuild.Player.ScriptCompilationSettings.extraScriptingDefines 仅适用于播放器构建,因此在定义适用于编辑器脚本的脚本符号时,请使用 PlayerSettings.SetScriptingDefineSymbols。这是配置播放器设置中平台特定脚本符号的代码等效方法。

重要:使用 SetScriptingDefineSymbols 从代码创建的符号在编辑器重新获得控制并重新编译脚本之前不会生效。例如,如果您在编辑器脚本中使用 SetScriptingDefineSymbols 创建脚本符号,然后在下一行调用 BuildPipeline.BuildPlayer,则前一行创建的新符号尚未生效。在这种情况下,作为 BuildPlayer 执行一部分运行的任何编辑器代码都将在没有新符号的情况下运行,播放器可能无法按预期构建。

(五)批处理模式下的自定义符号

当编辑器以批处理模式运行时,没有机制可以触发脚本的重新编译。如果您需要在以批处理模式运行的编辑器中定义特定的符号,它们必须通过 csc.rsp 资产文件在启动时就到位。

(六)脚本符号继承

如果您在多个位置定义了自定义脚本符号,Unity 会将所有适用于当前构建配置的符号加在一起。符号是从每个作用域继承的,而不是被覆盖,具体如下:

  • 项目范围符号(来自 csc.rsp
  • 平台特定符号(来自播放器设置)
  • 构建配置文件符号(来自构建数据)

仅当与活动构建配置文件匹配时,才会包含平台和构建配置文件符号。

例如,假设您的项目在以下位置定义了以下自定义脚本符号:

位置定义的符号
csc.rspSYMBOL_A
Windows Player SettingSYMBOL_B
WindowsBuildProfile1SYMBOL_C
WindowsBuildProfile2SYMBOL_D

在此示例配置中,当不同的构建配置文件处于活动状态时,以下表格显示了哪些符号适用于您的编辑器和播放器代码:

Active Build ProfileActive Symbols
AndroidSYMBOL_A
WindowsSYMBOL_A, SYMBOL_B
WindowsBuildProfile1SYMBOL_A, SYMBOL_B, SYMBOL_C
WindowsBuildProfile2SYMBOL_A, SYMBOL_B, SYMBOL_D

您可以使用代码中的 #if 指令来测试这种行为。有关更多信息,请参阅 测试条件编译。

三、测试条件编译

以下示例展示了如何测试您的条件编译代码。它还根据为目标构建选择的平台在控制台中打印一条消息。

(一)示例代码

using UnityEngine;
using System.Collections;

public class PlatformDefines : MonoBehaviour {
    void Start () {

        #if UNITY_EDITOR
            Debug.Log("Unity Editor");
        #endif

        #if UNITY_IOS
            Debug.Log("Unity iOS");
        #endif

        #if UNITY_STANDALONE_OSX
            Debug.Log("Standalone OSX");
        #endif

        #if UNITY_STANDALONE_WIN
            Debug.Log("Standalone Windows");
        #endif

    }          
}

(二)测试步骤

  1. 打开 Build Profiles 窗口(菜单:File > Build Profiles)。
  2. 检查您要测试代码的平台是否为活动平台配置文件。如果不是,请选择您首选的平台并点击 Switch Profile
  3. 创建一个脚本并复制粘贴上述示例代码。
  4. Game View Toolbar,点击 Play 按钮进入播放模式。通过检查 Unity 控制台中与所选平台相关的消息,确认代码是否正常工作。例如,如果您选择 iOS,则控制台中会出现 Unity EditorUnity iOS 的消息。

参考:

  1. https://docs.unity3d.com/Manual/scripting-symbol-reference.html

  2. https://docs.unity3d.com/Manual/custom-scripting-symbols.html


原文地址:https://blog.csdn.net/tealcwu/article/details/145093456

免责声明:本站文章内容转载自网络资源,如侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!