关于 unity-platforms
面向 Unity 开发者的跨平台开发参考技能,汇总平台构建配置、条件编译、移动端与 WebGL 注意事项,以及 IL2CPP、Mono 和 Addressables 的用法。适合规划平台配置并排查构建与性能问题。
主要功能
- 01Build Profiles 与场景配置
- 02平台条件编译宏
- 03iOS 与 Android 设置和优化
- 04WebGL 内存与 JavaScript 互操作
- 05IL2CPP 与 Mono 对比
- 06Addressables 资源加载
适用场景
- 01为不同平台维护独立构建配置
- 02添加平台专属代码或功能
- 03优化移动端与 WebGL 的资源和内存
- 04选择脚本后端并配置资源加载
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ nice-wolf-studio/ unity-claude-skills --skill unity-platforms安装后在 Claude Code 中输入/unity-platforms确认已加载。
附带文件references/mobile-optimization.mdreferences/platform-defines.md
详细介绍
Unity 平台技能
支持的平台
Unity 6 支持以下平台类别:
- 桌面:Windows、macOS、Linux
- 移动:Android、iOS
- 新兴平台:visionOS、tvOS
- Web:WebGL(包括 Facebook Instant Games)
- 服务器:专用服务器
- 嵌入式:Embedded Linux、QNX
- UWP:Universal Windows Platform
- 封闭平台:PlayStation、Xbox(Game Core)、Nintendo(需要保密/法律协议,并通过 Platform Module Installation 注册)
构建配置文件和设置
构建配置文件取代了旧版 Build Settings 窗口。构建配置文件是一组配置设置,用于为特定平台构建应用程序。
两种配置文件类型
- 平台:显示当前已安装的平台,各配置共享相同设置。启用 Development Build 等选项后,该设置将应用于所有配置。各平台配置文件共享相同的场景数据。
- 构建配置文件:独立配置,不与其他平台共享。每个配置文件都可以指定独有的场景和设置。配置文件以资产文件形式存储,兼容版本控制。
主要功能
- 自定义名称,以便整理多个构建配置
- 集成版本控制(配置文件以资产文件形式存储)
- 为每个配置文件分配场景
- 开发版构建(调试符号、Profiler 访问权限)和发布版构建
- 通过 File > Build Profiles 访问
- 右键单击平台,然后选择“Copy to new profile”即可复制平台
场景管理
场景按配置文件进行管理。你可以在构建中添加、排除、移除和重新排序场景。每个唯一的 Scene 文件都代表一个独立的关卡或屏幕。
平台脚本定义
使用 #if 指令按平台有条件地编译代码。
平台定义
| 定义 | 平台 |
|---|---|
UNITY_EDITOR | 任意 Editor 代码 |
UNITY_EDITOR_WIN | Windows Editor |
UNITY_EDITOR_OSX | macOS Editor |
UNITY_EDITOR_LINUX | Linux Editor |
UNITY_STANDALONE_OSX | macOS Standalone |
UNITY_STANDALONE_WIN | Windows Standalone |
UNITY_STANDALONE_LINUX | Linux Standalone |
UNITY_STANDALONE | 任意 Standalone(Win/Mac/Linux) |
UNITY_SERVER | 专用服务器 |
UNITY_IOS | iOS |
UNITY_ANDROID | Android |
UNITY_TVOS | tvOS |
UNITY_VISIONOS | visionOS |
UNITY_WEBGL | WebGL |
UNITY_WSA | Universal Windows Platform |
UNITY_WSA_10_0 | UWP 10.0 |
UNITY_EMBEDDED_LINUX | Embedded Linux |
UNITY_QNX | QNX |
UNITY_FACEBOOK_INSTANT_GAMES | Facebook Instant Games |
功能和后端定义
| 定义 | 含义 |
|---|---|
UNITY_ANALYTICS | 已启用 Analytics |
UNITY_ASSERTIONS | 已启用断言 |
UNITY_64 | 64 位平台 |
ENABLE_MONO | Mono 脚本后端 |
ENABLE_IL2CPP | IL2CPP 脚本后端 |
ENABLE_VR | 已启用 VR 支持 |
ENABLE_INPUT_SYSTEM | 已启用新 Input System |
ENABLE_LEGACY_INPUT_MANAGER | 已启用旧版 Input Manager |
ENABLE_WINMD_SUPPORT | WinMD 支持 |
DEVELOPMENT_BUILD | 开发版构建 |
UNITY_CLOUD_BUILD | Cloud Build |
.NET API 级别定义
| 定义 | API 级别 |
|---|---|
NET_STANDARD_2_0 | .NET Standard 2.0 |
NET_STANDARD_2_1 | .NET Standard 2.1 |
NET_STANDARD / NETSTANDARD | 任意 .NET Standard |
NETSTANDARD2_1 | .NET Standard 2.1(C# 定义) |
NET_4_6 | .NET Framework |
NET_2_0 / NET_LEGACY | .NET 2.0(旧版) |
CSHARP_7_3_OR_NEWER | 可用 C# 7.3 或更高版本 |
版本定义
格式:UNITY_X、UNITY_X_Y、UNITY_X_Y_Z、UNITY_X_Y_OR_NEWER
Unity 6000.0.33 示例:
UNITY_6000、UNITY_6000_0、UNITY_6000_0_33、UNITY_6000_0_OR_NEWER
移动平台优化
iOS
架构:仅支持 ARM64(不支持 ARMv7)。
脚本后端:iOS 必须使用 IL2CPP(不支持 Mono 选项)。
Player 设置(Edit > Project Settings > Player > iOS):
- Bundle Identifier:
com.CompanyName.ProductName - 签名 Team ID + 为 Xcode 启用自动签名
- 可选择目标最低 iOS 版本
- 用于调试着色器问题的 Metal API Validation
- 在非默认方向下提升性能的 Metal Write-Only Backbuffer
- 在 Metal 上强制使用硬阴影(通过点采样提升性能)
- 方向:纵向、横向或自动旋转,并可设置允许的方向
- 启动画面:默认、图像或自定义 Storyboard
- 要求支持 ARKit 时,设备必须为 iPhone 6s 或更高版本,且系统为 iOS 11 或更高版本
Android
架构:ARMv7 和 ARM64(ARM64 必须使用 IL2CPP)。
Player 设置(Edit > Project Settings > Player > Android):
- Package Name:
com.YourCompanyName.YourProductName - 最低 API 级别和目标 API 级别
- Graphics API:自动(优先 Vulkan,回退到 GLES)、Vulkan 或 OpenGL ES 3.x
- 按目标架构拆分 APK,以减小 Google Play 上的下载体积
- 用于签名的 Keystore 配置(生产环境使用自定义 keystore)
- 脚本后端:Mono 或 IL2CPP
- API 兼容性:.NET Framework 或 .NET Standard 2.1
- 托管代码剥离级别:最低到高
主要差异:不同型号的 Android 设备在硬件能力上差异很大。请在多台设备上进行测试。
移动端优化技巧
- 使用 ASTC 纹理压缩(现代 iOS 和 Android 设备均支持)
- 通过批处理(静态和动态)尽量减少绘制调用
- 使用 AssetBundles 或 Addressables 按需加载内容
- 使用 Unity Profiler 和平台专用工具进行分析
- 降低移动 GPU 上的着色器复杂度
WebGL 注意事项
内存管理
- Unity 堆通过 WebAssembly Memory 实现(可调整大小的 ArrayBuffer)
- 堆最多可扩展至 4 GB(Player 设置中的 Maximum Memory Size)
- 资源数据从
.data文件解包到虚拟内存文件系统(Emscripten)中 - 垃圾回收器仅在每帧结束时运行(帧中不会进行回收)
- 可用内存取决于设备、操作系统、浏览器(32/64 位)和标签页隔离模型
内存优化
在循环中使用 StringBuilder,而不是字符串拼接:
// BAD: Creates ~15 GB temporary allocations for 100k iterations
string hugeString = "";
for (int i = 0; i < 100000; i++)
hugeString += "foo";
// GOOD: Pre-allocated StringBuilder
var sb = new StringBuilder();
for (int i = 0; i < 10000; i++)
sb.Append("foo");
使用 NativeArray<T> 进行临时分配,以绕过 GC:
using (var data = new NativeArray<byte>(size, Allocator.Temp))
{
// Memory freed immediately upon scope exit
}
使用 AssetBundles 加载资源(直接下载到 Unity 堆中,不会额外占用浏览器分配的内存)。
启用 Data Caching(IndexedDB/Caching APIs)以减少重复下载。
JavaScript 互操作
Unity 支持两种 JavaScript 插件文件类型:
- .jslib:定义可从 C# 代码调用的函数
- .jspre:包含现有 JavaScript 库
限制:.jslib 和 .jspre 文件仅支持 ECMAScript 5(ES5)语法,暂不支持 ES6。
.jslib 插件示例
// Assets/Plugins/WebGL/MyPlugin.jslib
mergeInto(LibraryManager.library, {
ShowAlert: function (message) {
window.alert(UTF8ToString(message));
},
});
C# 调用 JavaScript
using System.Runtime.InteropServices;
using UnityEngine;
public class WebGLBridge : MonoBehaviour
{
[DllImport("__Internal")]
private static extern void ShowAlert(string message);
void Start()
{
#if UNITY_WEBGL && !UNITY_EDITOR
ShowAlert("Hello from Unity!");
#endif
}
}
IL2CPP 与 Mono
IL2CPP(中间语言转 C++)
IL2CPP 是 Unity 自定义的 AOT 脚本后端,可通过 C++ 将 C# 转换为原生代码。
转换流程:
- Roslyn 编译器将 C# 转换为 .NET 托管程序集(DLL)
- 托管代码裁剪可减小应用体积
- 将所有托管程序集转换为标准 C++ 代码
- C++ 编译器生成特定于平台的机器码
- 创建可执行文件、DLL、APK/AAB 或应用包
优点:
- 与 Mono 相比,运行时性能更好
- 应用启动时间更短
- 支持所有平台
- 支持与 Mono 完全相同的托管代码调试
缺点:
- 构建时间比 Mono 长得多
- 最终应用体积更大
- 通常不支持交叉编译(必须在目标操作系统上构建)
- 例外:支持从任意桌面平台交叉编译到 Linux
配置:
- Player Settings:Edit > Project Settings > Player > Configuration > Scripting Backend
- 脚本 API:
PlayerSettings.SetScriptingBackend
构建速度优化:
- 将项目文件夹从反恶意软件扫描中排除
- 使用速度最快的可用存储设备
- 选择“Optimize for code size and build time”(以运行时性能为代价)
- 对兼容代码同时使用 Burst 编译器和 IL2CPP
Mono
- 构建速度更快(JIT 编译)
- 构建输出更小
- 并非所有平台都支持(iOS 要求使用 IL2CPP)
- 运行时性能不如 IL2CPP
如何选择
| 标准 | IL2CPP | Mono |
|---|---|---|
| iOS 构建 | 必需 | 不支持 |
| Android 构建 | ARM64 推荐使用 | 支持 ARMv7 |
| 构建迭代速度 | 较慢 | 较快 |
| 运行时性能 | 更好 | 良好 |
| 主机平台 | 必需 | 不支持 |
| WebGL | 必需 | 不支持 |
Addressables 概述
Addressable Asset System(com.unity.addressables v2.9.1)支持通过地址而非直接路径引用资源。
核心概念
- 将任意资源标记为“addressable”,即可生成可从任何位置调用的唯一地址
- 支持从本地或远程位置加载
- 使用异步加载,并自动解析依赖项
- 可替代直接引用、传统资源包和 Resources 文件夹
- 访问路径:Window > Asset Management > Addressables
基本用法模式
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.AsyncOperations;
public class AddressableLoader : MonoBehaviour
{
[SerializeField] private AssetReference prefabRef;
async void Start()
{
AsyncOperationHandle<GameObject> handle =
Addressables.InstantiateAsync(prefabRef);
await handle.Task;
if (handle.Status == AsyncOperationStatus.Succeeded)
{
Debug.Log("Asset loaded successfully");
}
}
void OnDestroy()
{
// Always release when done
prefabRef.ReleaseAsset();
}
}
常见模式
特定于平台的代码
public class PlatformManager : MonoBehaviour
{
void Start()
{
#if UNITY_IOS
Application.targetFrameRate = 60;
#elif UNITY_ANDROID
Application.targetFrameRate = 60;
Screen.sleepTimeout = SleepTimeout.NeverSleep;
#elif UNITY_WEBGL
// WebGL runs at browser refresh rate
#elif UNITY_STANDALONE
Application.targetFrameRate = -1; // Uncapped
#endif
}
}
运行时平台检查
void ConfigureForPlatform()
{
switch (Application.platform)
{
case RuntimePlatform.IPhonePlayer:
SetupMobileControls();
break;
case RuntimePlatform.Android:
SetupMobileControls();
break;
case RuntimePlatform.WebGLPlayer:
SetupWebControls();
break;
default:
SetupDesktopControls();
break;
}
}
构建配置脚本
#if DEVELOPMENT_BUILD
Debug.Log("Development build active");
#endif
#if ENABLE_IL2CPP
// IL2CPP-specific code
#elif ENABLE_MONO
// Mono-specific code
#endif
反模式
-
什么都用 Resources 文件夹,而不使用 Addressables。Resources 文件夹会在启动时加载所有资源,增加内存占用和加载时间。
-
不使用平台定义,只依赖运行时检查。编译时定义可以将未使用的代码完全排除在构建之外。
-
在 WebGL 循环中进行字符串拼接。WebGL 中的 GC 只会在帧结束时运行,从而产生大量临时分配。请使用
StringBuilder或NativeArray<T>。 -
忽略 IL2CPP 的 AOT 限制。依赖反射的代码、
System.Reflection.Emit和运行时代码生成在 IL2CPP 下会失败。设计时应考虑 AOT。 -
启用 Development Build 后直接发布。开发构建包含 Profiler 开销和调试符号,会增大体积并降低性能。
-
未在 Android 上按架构拆分 APK。发布同时包含 ARMv7 和 ARM64 的单个大型 APK 会浪费用户流量。请使用 Split APKs 或 App Bundles。
-
硬编码平台路径。跨平台访问文件时,请使用
Application.persistentDataPath、Application.streamingAssetsPath和Application.temporaryCachePath。 -
未在实际设备上测试。Android 硬件差异很大。模拟器和仿真器无法体现真实的性能特征。
API 快速参考
| API | 用途 |
|---|---|
Application.platform | 检测运行时平台 |
RuntimePlatform enum | 用于运行时检查的平台常量 |
SystemInfo.graphicsDeviceType | 当前图形 API(Vulkan、Metal 等) |
SystemInfo.supportsComputeShaders | 检查是否支持计算着色器 |
PlayerSettings.SetScriptingBackend() | 通过脚本设置 IL2CPP 或 Mono |
Addressables.InstantiateAsync() | 加载并实例化可寻址资源 |
Addressables.LoadAssetAsync<T>() | 加载可寻址资源,但不实例化 |
AssetReference | 对可寻址资源的可序列化引用 |
Application.targetFrameRate | 设置目标帧率 |
Screen.sleepTimeout | 防止移动设备屏幕变暗 |
Application.persistentDataPath | 平台安全的可写数据路径 |
相关技能
- unity-graphics — 渲染管线、着色器和视觉效果
- unity-packages-services — Package Manager 工作流和 Unity Gaming Services