1. 为什么你需要掌握AssetBundle?
如果你正在用Unity做游戏,尤其是那种资源比较多的项目,比如有大量角色、场景、特效,或者想做热更新,那你迟早得和AssetBundle打交道。我刚开始接触的时候也觉得这玩意儿有点复杂,一堆概念,什么打包、依赖、加载策略,头都大了。但后来项目逼着我去用,踩过几次坑之后才发现,它其实就像我们平时整理文件一样,把不同的东西分门别类打包好,需要的时候再拿出来用,逻辑上并不难理解。
简单来说,AssetBundle(后面我们简称AB包)就是Unity提供的一种资源打包格式。你可以把游戏里的模型、贴图、预制体、场景甚至脚本(以资源形式)都塞进一个AB包里。它的核心价值有两个:一是资源管理,你可以按功能模块(比如“主城场景包”、“英雄皮肤包”)来组织资源,让项目结构更清晰;二是动态加载与热更新,游戏运行时可以从本地或者网络服务器下载新的AB包并加载里面的资源,这样你就不用为了更新一个角色皮肤而让玩家重新下载整个游戏安装包。
很多新手可能会问,Unity不是有Resources文件夹吗?直接把资源放里面,用Resources.Load加载不就行了?确实可以,但Resources有硬伤:它打包后是只读的,无法在发布后修改或追加。这意味着所有资源在构建时就被“焊死”在游戏里了。而AB包是独立的外部文件,可以随时替换、追加,灵活性高得多。所以,对于任何有资源动态加载需求的商业项目,AB包几乎是必选项。
2. 动手之前:理清AssetBundle的核心概念
在开始写代码之前,我们先花几分钟把几个关键概念搞清楚,这能帮你避开很多后期的“坑”。我自己就曾经因为没理解“依赖关系”,导致打包出来的AB包巨大无比,或者运行时资源丢失。
2.1 什么是AssetBundle? 你可以把它想象成一个压缩包(.zip或.rar),但这个压缩包是Unity特制的。里面可以包含多种类型的资产(Assets)。每个AB包都有一个唯一的标识名,也就是我们常说的Bundle Name。在Unity编辑器中,你可以为任意一个资源(比如一个Prefab预制体)设置它属于哪个AB包。
2.2 资源的依赖关系 这是AB包系统里最重要也最容易出错的一点。假设你的游戏里有一个“英雄_张三”的预制体,这个预制体用到了一个“盔甲_金色”的材质球,而这个材质球又引用了一张“贴图_金属.jpg”。当你把“英雄_张三”这个预制体标记为要打入hero_zhangsan这个AB包时,Unity默认不会自动把材质和贴图也打进去。 如果你只加载了hero_zhangsan包并实例化预制体,游戏里可能会出现一个紫色的模型(材质丢失)。因为材质和贴图没有被一起加载。为了解决这个问题,你有两个选择:一是把材质和贴图也标记到同一个AB包里;二是把它们分别打到不同的包(比如material_gold和texture_metal),然后在加载hero_zhangsan包之前,先加载它所依赖的材质包和贴图包。Unity提供了工具来帮你分析和管理这些依赖,我们后面会详细说。
2.3 打包选项(BuildAssetBundleOptions) 在调用打包API时,你会看到一个BuildAssetBundleOptions参数。它控制着打包的一些行为,比如:
- None:最基础的选项。
- UncompressedAssetBundle:不打压压缩。这样打包出来的文件很大,但加载时不需要解压,速度最快。适合本地调试或对加载速度极度敏感的场景。
- ChunkBasedCompression (LZ4):这是Unity推荐也是目前最常用的选项。它使用LZ4压缩算法,在压缩率和加载速度之间取得了很好的平衡。加载时是流式解压,可以快速读取资源。
- DisableWriteTypeTree:禁用类型树。这会让AB包稍微小一点,但意味着不同Unity版本生成的AB包可能无法互相加载,除非版本完全相同。一般不建议关闭,除非你对包体大小有极致要求且能严格管控版本。
- DeterministicAssetBundle:确保打包结果具有确定性。即同样的资源输入,每次打包生成的AB包二进制内容完全一致。这对于需要做增量更新或版本对比的团队非常重要。
2.4 构建目标(BuildTarget) 这个参数指定AB包是给哪个平台用的。比如BuildTarget.StandaloneWindows64是给64位Windows电脑用的,BuildTarget.Android是给安卓用的,BuildTarget.iOS是给苹果手机用的。非常重要的一点是:不同平台的AB包不能混用! 你不能把打给Windows的包放到Android设备上去加载,会报错。所以通常我们会在打包脚本里根据当前项目的目标平台来设置这个参数。
3. 实战第一步:编写你的AssetBundle打包脚本
好了,理论铺垫得差不多了,我们直接上手写代码。我会带你写一个比原始文章里更健壮、功能更完整的打包脚本。
3.1 创建基础的打包脚本 就像原始文章里说的,我们首先在Unity项目的Assets/Editor文件夹下创建一个C#脚本。如果Editor文件夹不存在,就新建一个。这个文件夹下的脚本只在Unity编辑器环境下运行,不会被打进游戏包里。
我们来创建一个叫AssetBundleBuilder.cs的脚本。
using System.IO;
using UnityEditor;
using UnityEngine;
public class AssetBundleBuilder
{
// 在Unity编辑器菜单栏添加一个选项
[MenuItem("Tools/AssetBundle/构建所有AB包")]
static void BuildAllAssetBundles()
{
// 1. 定义输出目录
string outputPath = "Assets/StreamingAssets/AssetBundles";
// 2. 确保输出目录存在
if (!Directory.Exists(outputPath))
{
Directory.CreateDirectory(outputPath);
}
// 3. 执行打包
BuildPipeline.BuildAssetBundles(
outputPath,
BuildAssetBundleOptions.ChunkBasedCompression, // 使用推荐的LZ4压缩
EditorUserBuildSettings.activeBuildTarget // 自动使用当前项目的构建目标
);
// 4. 打包完成后提示
Debug.Log($"Asset
4986



被折叠的 条评论
为什么被折叠?



