Understanding Automatic Memory Management
特殊文件夹和脚本编译顺序

平台相关的编译

Unity 包括名为__平台相关的编译 (Platform Dependent Compilation)__ 的功能。此功能包括一些预处理器指令,可让您对脚本进行分区,从而为受支持平台之一专门编译和执行一段代码。

您可以在 Unity Editor 中运行此代码,这样便可专门为目标平台编译代码并在 Editor 中对其进行测试!

平台 #define 指令

Unity 支持对脚本使用的平台 #define 指令如下:

属性: 功能:
UNITY_EDITOR 用于从游戏代码中调用 Unity Editor 脚本的 #define 指令。
UNITY_EDITOR_WIN 用于 Windows 上的 Editor 代码的 #define 指令。
UNITY_EDITOR_OSX 用于 Mac OS X 上的 Editor 代码的 #define 指令。
UNITY_STANDALONE_OSX 用于专门为 Mac OS X(包括 Universal、PPC 和 Intel 架构)编译/执行代码的 #define 指令。
UNITY_STANDALONE_WIN 用于专门为 Windows 独立平台应用程序编译/执行代码的 #define 指令。
UNITY_STANDALONE_LINUX 用于专门为 Linux 独立平台应用程序编译/执行代码的 #define 指令。
UNITY_STANDALONE 用于为任何独立平台(Mac OS X、Windows 或 Linux)编译/执行代码的 #define 指令。
UNITY_WII 用于为 Wii 游戏主机编译/执行代码的 #define 指令。
UNITY_IOS 用于为 iOS 平台编译/执行代码的 #define 指令。
UNITY_IPHONE 已弃用。改用 UNITY_IOS
UNITY_ANDROID 用于 Android 平台的 #define 指令。
UNITY_PS4 用于运行 PlayStation 4 代码的 #define 指令。
UNITY_XBOXONE 用于执行 Xbox One 代码的 #define 指令。
UNITY_TIZEN 用于 Tizen 平台的 #define 指令。
UNITY_TVOS 用于 Apple TV 平台的 #define 指令。
UNITY_WSA 用于通用 Windows 平台的 #define 指令。此外,根据 .NET Core 和使用 .NET 脚本后端来编译 C# 文件时会定义 NETFX_CORE
UNITY_WSA_10_0 用于通用 Windows 平台的 #define 指令。此外,根据 .NET Core 来编译 C# 文件时会定义 WINDOWS_UWP
UNITY_WINRT UNITY_WSA 相同。
UNITY_WINRT_10_0 等效于 UNITY_WSA_10_0
UNITY_WEBGL 用于 WebGL 的 #define 指令。
UNITY_FACEBOOK 用于 Facebook 平台(WebGL 或 Windows 独立平台)的 #define 指令。
UNITY_ADS 用于从游戏代码中调用 Unity Ads 方法的 #define 指令。5.2 及更高版本。
UNITY_ANALYTICS 用于从游戏代码中调用 Unity Analytics 方法的 #define 指令。5.2 及更高版本。
UNITY_ASSERTIONS 用于断言控制过程的 #define 指令。

从 Unity 2.6.0 开始,可有选择地编译代码。可用选项取决于所使用的 Editor 版本。 如果版本号为 X.Y.Z__(例如,2.6.0),Unity 将使用以下格式公开三个全局 #define 指令:__UNITY_XUNITY_X_YUNITY_X_Y_Z

以下是 Unity 5.0.1 中公开的 #define 指令的示例:

UNITY_5 用于 Unity 5 发行版的 #define 指令,在每个 5.X.Y 版本中公开。
UNITY_5_0 用于 Unity 5.0 主要版本的 #define 指令,在每个 5.0.Z 版本中公开。
UNITY_5_0_1 用于 Unity 5.0.1 次要版本的 #define 指令。

从 Unity 5.3.4 开始,可根据编译或执行给定代码部分所需的最早 Unity 版本来有选择地编译代码。如果采用与上面相同的版本格式 (X.Y.Z),Unity 将以 UNITY_X_Y_OR_NEWER 格式公开一个可用于此目的的全局 #define。

支持的 #define 指令为:

CSHARP_7_3_OR_NEWER Defined when building scripts with support for C# 7.3 or newer.
ENABLE_MONO 用于 Mono 的脚本后端 #define。
ENABLE_IL2CPP 用于 IL2CPP 的脚本后端 #define。
NET_2_0 在 Mono 和 IL2CPP 上根据 .NET 2.0 API 兼容性级别构建脚本时定义。
NET_2_0_SUBSET 在 Mono 和 IL2CPP 上根据 .NET 2.0 Subset API 兼容性级别构建脚本时定义。
NET_LEGACY Defined when building scripts against .NET 2.0 or .NET 2.0 Subset API compatibility level on Mono and IL2CPP.
NET_4_6 在 Mono 和 IL2CPP 上根据 .NET 4.x API 兼容性级别构建脚本时定义。
NET_STANDARD_2_0 在 Mono 和 IL2CPP 上根据 .NET 标准 2.0 API 兼容性级别构建脚本时定义。
ENABLE_WINMD_SUPPORT Defined when Windows Runtime support is enabled on IL2CPP. See Windows Runtime Support for more details.

可使用 DEVELOPMENT_BUILD #define 来确定脚本是否正在启用了“Development Build”选项的情况下构建的播放器中运行。

还可根据脚本后端有选择地编译代码。

测试预编译的代码

下面是如何使用预编译代码的示例。该示例根据为目标构建选择的平台打印一条消息。

首先,通过 File > Build Settings 选择要测试代码的平台。随后将显示 Build Settings 窗口;从此处选择目标平台。

在 Build Settings 窗口中选择PC, Mac & Linux作为目标平台
在 Build Settings 窗口中选择“PC, Mac & Linux”作为目标平台

选择要测试预编译代码的平台,然后单击 Switch Platform 向 Unity 告知您所需的目标平台。

创建脚本并复制/粘贴以下代码:

// C#
using UnityEngine;
using System.Collections;

public class PlatformDefines : MonoBehaviour {
  void Start () {

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

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

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

  }          
}

要测试代码,请单击 Play Mode。通过在 Unity 控制台中检查相关消息来确认代码是否正常工作,具体取决于选择的平台;例如,如果选择 __iOS__,则消息“Iphone”设置为显示在控制台中。

在 C# 中,可使用 CONDITIONAL 属性,这是一种更简洁、更不容易出错的函数剥离方式。请参阅 ConditionalAttribute 类以了解更多信息。 请注意,常见的 Unity 回调(例如:Start()、Update()、LateUpdate()、FixedUpdate()、Awake())不受此属性的影响,因为它们是直接从引擎调用的,并且出于性能原因,此属性不会考虑它们。

除了基本的 #if 编译器指令外,还可在 C# 中使用多路测试:


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

# elif UNITY_IOS
    Debug.Log("Unity iPhone");

# else
    Debug.Log("Any other platform");

# endif


平台自定义 #define 指令

It is also possible to add to the built-in selection of #define directives by supplying your own. Open the Other Settings panel of the Player settings and navigate to the Scripting Define Symbols text box.

输入要为该特定平台定义的符号名称,以分号分隔。随后可以将这些符号用作 #if 指令中的条件,就像内置条件一样。

全局自定义 #define 指令

您可以定义自己的预处理器指令来控制在编译时包含的代码。为此,必须将包含额外指令的文本文件添加到 Assets 文件夹。文件名取决于您使用的语言。扩展名为 __.rsp__:

C#(播放器和 Editor 脚本) <项目路径>/Assets/mcs.rsp

举例来说,如果在 mcs.rsp 文件中包含单行 -define:UNITY_DEBUG,则 #define 指令 UNITY_DEBUG 将作为 C# 脚本的全局 #define 指令存在,但 Editor 脚本除外。

每次对 .rsp 文件进行更改时,都需要重新编译才能使更改生效。可通过更新或重新导入单个脚本(.js 或 .cs)文件来完成此操作。

注意

If you want to modify only global #define directives, use Scripting Define Symbols in Player settings, because this covers all the compilers. If you choose the .rsp files instead, you need to provide one file for every compiler Unity uses.

The use of .rsp files is described in the ‘Help’ section of the mcs application, which is included in the Editor installation folder. You can get more information by running mcs -help.

请注意,.rsp 文件需要与正在调用的编译器匹配。例如:

  • when targeting the .NET 3.5 Equivalent (deprecated) scripting runtime version, mcs is used with mcs.rsp, and
  • when targeting the .NET 4.x Eqivalent scripting runtime version compiler, csc is used with csc.rsp.

  • 2018–03–16 Page amended with no editorial review

  • 删除了三星电视支持。

Understanding Automatic Memory Management
特殊文件夹和脚本编译顺序