在 Unity 中,确定哪些内容会被打包到最终生成的游戏中,以及如何手动修改或忽略某些内容,涉及资源管理、构建流程和优化策略。以下是详细的解答,涵盖如何识别、控制和优化打包内容:
1. 确定哪些内容会被打包到最终生成的游戏中
Unity 的构建系统会根据以下规则决定哪些资源会被打包到最终的游戏中:
(1) 场景(Scenes)
- 默认规则:所有在 Build Settings(构建设置,
File > Build Settings
)中勾选的场景(Scenes in Build)都会被打包。 - 如何检查:
- 打开
Build Settings
窗口,查看列出的场景列表。 - 确保只勾选需要的场景,未勾选的场景不会被打包。
- 注意:场景中引用的所有资源(包括脚本、材质、纹理、模型、音频等)都会被自动包含,除非被显式忽略。
(2) 资源(Assets)
- 被场景引用的资源:
- 如果一个资源(例如纹理、模型、脚本、预制体等)被某个构建中的场景直接或间接引用(通过组件、脚本、预制体等),它会被自动打包。
- 例如,一个 GameObject 上附加的材质引用的纹理,或者脚本中动态加载的资源(如果在
Resources
文件夹或通过 AssetBundle 引用)。
- Resources 文件夹:
Assets/Resources
文件夹中的所有资源都会被打包,无论是否被场景直接引用,因为 Unity 假设这些资源可能通过Resources.Load
动态加载。
- AssetBundle:
- 如果使用 AssetBundle,只有标记为特定 AssetBundle 的资源会在构建时被打包为 AssetBundle,而不是直接包含在主构建中。
- StreamingAssets 文件夹:
Assets/StreamingAssets
文件夹中的文件会被原样复制到最终构建中,常用于存储需要运行时访问的原始文件(如 JSON、视频等)。
- 代码(Scripts):
- 所有在
Assets
文件夹中的脚本都会被编译并包含在构建中,但只有被场景或预制体引用的脚本会实际生成 IL 代码。 - 未被引用的脚本可能仍然包含在构建中(因 Mono 编译器行为),但可以通过代码裁剪(Code Stripping)优化。
(3) Unity 内置资源和设置
- Player Settings:
Edit > Project Settings > Player
中的设置(如图标、分辨率、渲染设置等)会影响构建内容。
- Quality Settings:
- 不同平台的 Quality Settings(
Edit > Project Settings > Quality
)会影响打包的资源质量(例如纹理压缩格式)。
- Plugins:
Assets/Plugins
文件夹中的插件(例如 DLL、原生代码)会根据目标平台的设置被包含。
- Shader 和材质:
- 所有被场景或预制体引用的 Shader,以及 Unity 的内置 Shader(如果被材质引用)都会被打包。
(4) 其他隐式包含的内容
- 字体、UI 相关资源:如果使用了 TextMeshPro 或 UI 系统,相关的字体和 Sprite Atlas 会被自动包含。
- 物理材质、动画等:被场景或预制体引用的物理材质、动画片段等也会被打包。
- 编辑器设置:某些编辑器相关设置(如
Editor
文件夹中的脚本)不会被打包,因为它们仅用于编辑器环境。
如何检查具体打包内容
- Build Report:
- 构建完成后,Unity 会生成一个 Build Report,显示包含的资源、大小和依赖关系。
- 打开
Editor.log
文件(位于~/Library/Logs/Unity/
或%USERPROFILE%\AppData\Local\Unity\Editor\
),搜索 "Used Assets" 部分,查看被打包的资源列表及其大小。
- Asset Dependency Viewer:
- 使用 Unity 的
AssetDatabase
或第三方工具(如 Asset Hunter)分析资源依赖,查看哪些资源被场景或预制体引用。
- Build Size Analyzer:
- Unity 提供 Build Size Analyzer(在
Window > Analysis > Build Report Inspector
中,Unity 2019.3+)来可视化构建内容,显示每个资源的大小和来源。
2. 如何手动修改或忽略哪些内容被打包
为了优化构建大小或排除不需要的资源,可以手动控制打包的内容。以下是具体方法:
(1) 管理场景
- 移除不需要的场景:
- 在
Build Settings
中,取消勾选不需要的场景。 - 确保只添加必要的场景到
Scenes in Build
列表。
- 优化场景内容:
- 检查场景中的 GameObject,确保只引用必要的资源。
- 删除未使用的预制体、材质或其他组件。
- 动态加载场景:
- 使用
SceneManager.LoadSceneAsync
动态加载场景,而不是将所有场景都打包到主构建中。
(2) 管理资源
- 移除未使用的资源:
- Unity 不会打包未被引用的资源(
Resources
文件夹除外)。使用Find References in Scene
(右键资源)检查资源是否被使用。 - 删除或移动未使用的资源到
Editor
文件夹(不参与构建)。
- Resources 文件夹优化:
- 尽量避免使用
Resources
文件夹,因为其中所有内容都会被打包。 - 如果必须使用,确保只包含必要资源,并定期清理。
- AssetBundle:
- 将不常使用的资源(如关卡数据、大型纹理)标记为 AssetBundle,通过运行时加载减少主构建大小。
- 在
Inspector
中为资源设置 AssetBundle 标签,然后使用BuildPipeline.BuildAssetBundles
构建。
- StreamingAssets:
- 仅将运行时必需的原始文件放入
StreamingAssets
,并定期清理不需要的文件。
(3) 代码裁剪(Code Stripping)
- 启用代码裁剪:
- 在
Player Settings > Other Settings
中启用 Strip Engine Code 和 Managed Stripping Level(建议设置为 High)。 - 这会移除未使用的引擎代码和托管代码,减少构建大小。
- 注意:
- 裁剪可能导致运行时错误(如反射依赖的代码被移除)。使用
[Preserve]
属性或link.xml
文件保留必要代码。 - 示例
link.xml
:<linker> <assembly fullname="MyAssembly" preserve="all"/> <type fullname="MyNamespace.MyClass" preserve="all"/> </linker>
- 放置
link.xml
在Assets
文件夹中。
(4) Shader 优化
- Shader Variant Collection:
- 创建 Shader Variant Collection(
Assets > Create > Shader Variant Collection
),手动指定需要打包的 Shader 变体。 - 在
Project Settings > Graphics
中添加 Shader Variant Collection,减少不必要的 Shader 变体。
- 移除未使用的 Shader:
- 检查材质,确保只使用必要的 Shader。
- 使用
Shader Stripping
设置(Project Settings > Graphics
)移除未使用的 Shader。
(5) 纹理和模型优化
- 纹理压缩:
- 在
Inspector
中为纹理选择合适的压缩格式(例如 ETC2 for Android, ASTC for iOS)。 - 使用
Override for Platform
选项为不同平台设置不同的压缩格式。
- 模型优化:
- 在模型的
Model
选项卡中,禁用不需要的导入设置(如Read/Write Enabled
、Import Blendshapes
等)。 - 使用 LOD(Level of Detail)减少高细节模型的资源占用。
- Sprite Atlas:
- 使用 Sprite Atlas 打包 UI 纹理,减少 Draw Call 和构建大小。
- 在
Project Settings > Editor
中启用Sprite Atlas > Include in Build
。
(6) 忽略特定资源
- 移动到 Editor 文件夹:
- 将仅用于编辑器的资源(如编辑器脚本、调试工具)放入
Assets/Editor
文件夹,这些资源不会被打包。
- 使用 AssetPostprocessor:
- 编写自定义
AssetPostprocessor
脚本,自动过滤或修改资源导入设置。例如:public class CustomAssetPostprocessor : AssetPostprocessor { void OnPreprocessTexture() { if (assetPath.Contains("IgnoreThisFolder")) { TextureImporter importer = (TextureImporter)assetImporter; importer.isReadable = false; // 禁用读写,减少内存占用 } } }
- 条件编译:
- 使用条件编译指令(如
#if UNITY_EDITOR
)将调试代码限制在编辑器环境中,不会被打包到构建中。
(7) 第三方工具
- Asset Hunter Pro:
- 一个 Unity Asset Store 插件,用于分析未使用的资源并删除。
- Addressables:
- 使用 Unity 的 Addressable Asset System 替代
Resources
和 AssetBundle,精细控制资源加载和打包。 - 设置 Addressable 组,将资源标记为按需加载,减少主构建内容。
- 示例:将资源拖入 Addressable 组,设置
Load Path
为远程或本地。
3. 哪些内容不应该被打包
以下是一些通常不应该被打包的内容,以及如何避免:
- 编辑器专用资源:
Editor
文件夹中的脚本、工具和设置(自动忽略)。- 解决方法:确保这些资源位于
Assets/Editor
文件夹。
- 未使用的资源:
- 未被场景或脚本引用的资源(除非在
Resources
文件夹)。 - 解决方法:删除或移动到非
Assets
目录,使用 Asset Hunter 检查。
- 调试或测试资源:
- 测试场景、调试纹理、临时脚本等。
- 解决方法:不将测试场景添加到
Build Settings
,将测试资源移出Resources
。
- 冗余的 Shader 变体:
- 未使用的 Shader 变体会增加构建大小。
- 解决方法:使用 Shader Variant Collection 或 Shader Stripping。
- 大型未优化资源:
- 高分辨率纹理、未压缩音频、复杂模型等。
- 解决方法:优化资源设置,使用压缩格式,启用 LOD。
4. 最佳实践和注意事项
- 定期分析构建:
- 每次构建后检查
Editor.log
或 Build Report,找出占用空间最大的资源并优化。
- 版本控制:
- 在修改资源或删除未使用资源时,确保使用版本控制(如 Git),以便在出错时恢复。
- 自动化工具域:
- 使用脚本或 CI/CD 流程自动化资源清理和优化过程。
- 测试构建:
- 在目标平台上测试构建,确保没有遗漏必要资源或包含不必要的内容。
- Addressables 优先:
- 对于大型项目,优先使用 Addressables 系统,灵活管理资源加载,减少主构建大小。
5. 常见问题解答
- 如何知道哪些资源占用了最多空间?
- 查看
Editor.log
中的 Build Report,或使用 Build Report Inspector 分析。
- 如何防止 Resources 文件夹被打包?
- 将不需要动态加载的资源移出
Resources
文件夹,或使用 Addressables。
- 代码裁剪会导致问题吗?
- 如果使用了反射或动态加载,裁剪可能移除必要代码。使用
link.xml
或测试构建以确保功能正常。
- 如何处理不同平台的构建差异?
- 在
Player Settings
中为每个平台配置不同的设置(如纹理压缩、插件选择)。