04-02-源码-资源收集器(AssetBundleCollector)

源码-资源收集模块(AssetBundleCollector)

篇章 :04-源码深度-编辑器模块 阅读时间 :约 30 分钟 前置知识:了解 Editor 端整体架构


一、引言

本章将深入解析 YooAsset 资源收集模块(AssetBundleCollector)的源码实现。AssetBundleCollector 是 YooAsset 编辑器端的核心模块,负责资源的收集、分类和寻址配置。深入理解 AssetBundleCollector 的实现,是掌握 YooAsset 资源管理的基础。

AssetBundleCollector 采用了 Package/Group/Collector 的三级层级结构,提供了灵活的资源组织方式和强大的寻址能力。本章将从源码层面深入解析 AssetBundleCollector 的实现。


二、Package / Group / Collector 层级

2.1 三级层级结构

YooAsset 采用了 Package/Group/Collector 的三级层级结构来组织资源:

sql 复制代码
三级层级结构
├── Package(资源包)
│   ├── PackageName
│   ├── PackageVersion
│   └── 包含多个 Group
├── Group(资源分组)
│   ├── GroupName
│   ├── GroupDesc
│   └── 包含多个 Collector
└── Collector(资源收集器)
    ├── CollectPath
    ├── CollectorType
    └── 寻址配置

Package 详解:

Package 是 YooAsset 资源管理的最高层级,代表一个完整的资源包。每个 Package 有自己的名称、版本和清单(Manifest),可以独立打包、更新和加载。

Group 详解:

Group 是 Package 下的分组,将相关的 Collector 组织在一起。Group 用于对资源进行逻辑分组,便于管理。

Collector 详解:

Collector 是最细粒度的资源收集器,定义了具体的资源收集路径和规则。每个 Collector 对应一个或多个资源的收集。

2.2 Package 类实现

Package 类的实现位于 YooAsset/Editor/AssetBundleCollector/AssetBundlePackage.cs:

csharp 复制代码
public class AssetBundlePackage
{
    public string PackageName;
    public string PackageVersion;
    public string PackageDesc;
    public List<AssetBundleCollectorGroup> Groups = new List<AssetBundleCollectorGroup>();
}

PackageName 详解:

PackageName 是 Package 的唯一标识符,运行时通过 PackageName 加载 Package。

PackageVersion 详解:

PackageVersion 是 Package 的版本号,用于热更新时的版本比较。

PackageDesc 详解:

PackageDesc 是 Package 的描述信息,便于开发者理解 Package 的用途。

Groups 详解:

Groups 是 Package 下的所有 Group。每个 Group 包含多个 Collector。

2.3 Group 类实现

Group 类的实现位于 YooAsset/Editor/AssetBundleCollector/AssetBundleCollectorGroup.cs:

csharp 复制代码
public class AssetBundleCollectorGroup
{
    public string GroupName;
    public string GroupDesc;
    public EGroupPackRuleType PackRuleType = EGroupPackRuleType.CollectorPack;
    public AssetBundleCollectorGroupStrategy Strategy;
    public List<AssetBundleCollector> Collectors = new List<AssetBundleCollector>();
}

GroupName 详解:

GroupName 是 Group 的唯一标识符,用于在 Package 内唯一标识一个 Group。

PackRuleType 详解:

PackRuleType 决定了 Group 的打包规则:

  • CollectorPack:每个 Collector 单独打包
  • GroupPack:Group 内所有 Collector 合并打包
  • TopDirectoryPack:按顶级目录打包

Strategy 详解:

Strategy 是 Group 的策略,包含了 Group 的高级配置。

Collectors 详解:

Collectors 是 Group 下的所有 Collector。

2.4 Collector 类实现

Collector 类的实现位于 YooAsset/Editor/AssetBundleCollector/AssetBundleCollector.cs:

csharp 复制代码
public class AssetBundleCollector
{
    public ECollectorType CollectorType;
    public string CollectPath;
    public EAddressRule AddressRule;
    public string Address;
    public List<string> AssetTags;
    public List<IAssetBundleCollectorRule> Rules = new List<IAssetBundleCollectorRule>();
    public string UserData;
}

CollectorType 详解:

CollectorType 决定 Collector 的类型:

  • MainAssetCollector:主资源收集器
  • StaticAssetCollector:静态资源收集器
  • DependAssetCollector:依赖资源收集器

CollectPath 详解:

CollectPath 是 Collector 的资源收集路径,可以是文件夹或单个文件。

AddressRule 详解:

AddressRule 决定资源的寻址方式。

Address 详解:

Address 是 Collector 的自定义地址前缀。

Rules 详解:

Rules 是 Collector 的规则列表,包含了过滤规则和打包规则。


三、收集器工作流程

3.1 收集器初始化

收集器的初始化过程如下:

markdown 复制代码
收集器初始化
1. 加载 PackageScriptableObject
2. 解析 PackageScriptableObject
3. 创建 AssetBundlePackage 对象
4. 创建 AssetBundleCollectorGroup 对象
5. 创建 AssetBundleCollector 对象
6. 准备收集

PackageScriptableObject 详解:

PackageScriptableObject 是 Collector 配置的 ScriptableObject 形式,存储在项目 Asset 目录中。

配置加载详解:

配置加载时需要先读取 ScriptableObject,然后反序列化为内存对象。

3.2 资源扫描

资源扫描是 Collector 的核心工作:

csharp 复制代码
public class AssetBundleCollector
{
    public List<CollectAssetInfo> Scan()
    {
        List<CollectAssetInfo> result = new List<CollectAssetInfo>();
        
        if (CollectorType == ECollectorType.MainAssetCollector)
        {
            // 扫描主资源
            string[] files = Directory.GetFiles(CollectPath, "*", SearchOption.AllDirectories);
            foreach (string file in files)
            {
                if (IsValidAsset(file))
                {
                    result.Add(CreateCollectAssetInfo(file));
                }
            }
        }
        else if (CollectorType == ECollectorType.DependAssetCollector)
        {
            // 扫描依赖资源
            // ...
        }
        
        return result;
    }
}

主资源扫描详解:

主资源扫描会递归扫描 CollectPath 下的所有资源,并根据 IsValidAsset 方法判断资源是否有效。

依赖资源扫描详解:

依赖资源扫描会分析主资源的依赖关系,提取所有依赖资源。

有效性判断详解:

IsValidAsset 方法会根据过滤规则判断资源是否有效。

3.3 资源过滤

资源过滤是 Collector 的重要工作。YooAsset 提供了多种过滤规则:

文件扩展名过滤:

csharp 复制代码
public class FileExtensionFilter : IAssetBundleCollectorRule
{
    public string[] Extensions;
    public bool IsMatch(string assetPath)
    {
        string ext = Path.GetExtension(assetPath);
        return Extensions.Contains(ext);
    }
}

目录路径过滤:

csharp 复制代码
public class DirectoryFilter : IAssetBundleCollectorRule
{
    public string[] ExcludeDirectories;
    public bool IsMatch(string assetPath)
    {
        foreach (var dir in ExcludeDirectories)
        {
            if (assetPath.StartsWith(dir)) return false;
        }
        return true;
    }
}

文件名前缀过滤:

csharp 复制代码
public class FileNamePrefixFilter : IAssetBundleCollectorRule
{
    public string[] Prefixes;
    public bool IsMatch(string assetPath)
    {
        string fileName = Path.GetFileName(assetPath);
        foreach (var prefix in Prefixes)
        {
            if (fileName.StartsWith(prefix)) return true;
        }
        return false;
    }
}

四、寻址规则实现

4.1 String Address 寻址

String Address 是最常用的寻址方式:

csharp 复制代码
public class StringAddress
{
    public static string GetAddress(string assetPath, AssetBundleCollector collector)
    {
        string address = string.Empty;
        
        if (!string.IsNullOrEmpty(collector.Address))
        {
            // 使用自定义地址
            address = collector.Address + "/" + Path.GetFileNameWithoutExtension(assetPath);
        }
        else
        {
            // 使用资源相对路径
            string relativePath = assetPath.Substring(collector.CollectPath.Length);
            address = relativePath.Replace("\\", "/").TrimStart('/');
        }
        
        return address;
    }
}

自定义地址详解:

自定义地址使用 Collector 的 Address 作为前缀,加上文件名生成资源地址。

相对路径地址详解:

相对路径地址使用资源相对路径作为地址,去除扩展名。

4.2 GUID Address 寻址

GUID Address 使用资源的 GUID 作为地址:

csharp 复制代码
public class GuidAddress
{
    public static string GetAddress(string assetPath)
    {
        string guid = AssetDatabase.AssetPathToGUID(assetPath);
        return guid;
    }
}

GUID 详解:

GUID 是 Unity 为每个资源生成的唯一标识符。使用 GUID 作为地址可以避免地址冲突。

GUID 寻址的优缺点:

  • 优点:唯一、不冲突
  • 缺点:不可读、难以调试

4.3 Label Address 寻址

Label Address 使用资源的 Tag 作为寻址方式:

csharp 复制代码
public class LabelAddress
{
    public static List<string> GetAddresses(List<string> assetTags)
    {
        return assetTags;
    }
}

Tag 详解:

每个资源可以打多个 Tag。通过 Tag 可以批量访问资源。

Label 寻址的优缺点:

  • 优点:批量访问、灵活
  • 缺点:需要额外配置

4.4 寻址规则的选择

不同的寻址规则适用于不同的场景:

寻址规则 适用场景 优点 缺点
String Address 一般资源 易读、易记 可能冲突
GUID Address 重要资源 唯一、不冲突 不可读
Label Address 批量资源 灵活、批量 需要配置

选择建议:

  • 一般资源:使用 String Address
  • 重要资源:使用 GUID Address
  • 需要批量访问的资源:使用 Label Address

五、Collector 配置序列化

5.1 序列化为 ScriptableObject

Collector 配置通常存储在 ScriptableObject 中:

csharp 复制代码
[CreateAssetMenu(fileName = "AssetBundlePackageConfig", menuName = "YooAsset/Package Config")]
public class AssetBundlePackageConfig : ScriptableObject
{
    public string PackageName;
    public string PackageVersion;
    public string PackageDesc;
    public List<AssetBundleCollectorGroupConfig> Groups = new List<AssetBundleCollectorGroupConfig>();
}

ScriptableObject 详解:

ScriptableObject 是 Unity 提供的配置存储方式,可以在 Unity Editor 中编辑。

配置结构详解:

配置结构与运行时对象结构对应,便于序列化和反序列化。

5.2 序列化为 JSON

除了 ScriptableObject,Collector 配置也可以序列化为 JSON:

csharp 复制代码
public class AssetBundlePackageConfig
{
    public string ToJson()
    {
        return JsonUtility.ToJson(this, true);
    }
    
    public static AssetBundlePackageConfig FromJson(string json)
    {
        return JsonUtility.FromJson<AssetBundlePackageConfig>(json);
    }
}

JSON 序列化的优势:

  • 跨平台:JSON 可以在不同平台之间传输
  • 易于管理:可以使用版本控制管理 JSON 文件
  • 自动化:可以自动生成 JSON 配置

5.3 配置的版本管理

Collector 配置需要版本管理:

配置迁移:

当 YooAsset 升级时,配置可能需要迁移以适配新版本。

配置兼容性:

新版本的 YooAsset 应该能加载旧版本的配置。

配置升级:

提供配置升级工具,自动升级旧版本配置到新版本。


六、Collector 高级特性

6.1 自定义打包规则

开发者可以自定义打包规则:

csharp 复制代码
public interface IAssetBundleCollectorRule
{
    bool IsMatch(string assetPath);
    string GetBundleName(string assetPath, AssetBundleCollector collector);
}

自定义打包规则示例:

csharp 复制代码
public class CustomPackRule : IAssetBundleCollectorRule
{
    public bool IsMatch(string assetPath) => true;
    
    public string GetBundleName(string assetPath, AssetBundleCollector collector)
    {
        return $"custom_{Path.GetFileNameWithoutExtension(assetPath)}";
    }
}

6.2 资源标签

资源可以打标签,便于分类管理:

csharp 复制代码
public class AssetBundleCollector
{
    public List<string> AssetTags;
}

标签的使用:

标签可以用于:

  • 分类管理:按标签分类资源
  • 批量加载:通过标签批量加载资源
  • 资源筛选:按标签筛选资源

6.3 用户数据

Collector 支持用户自定义数据:

csharp 复制代码
public class AssetBundleCollector
{
    public string UserData;
}

用户数据的作用:

  • 扩展 Collector 的功能
  • 存储自定义信息
  • 配合自定义规则使用

七、总结

本章深入解析了 YooAsset 资源收集模块(AssetBundleCollector)的源码实现,包括:

  • 三级层级结构:Package、Group、Collector 的实现
  • 收集器工作流程:初始化、扫描、过滤的实现
  • 寻址规则实现:String、GUID、Label 三种寻址方式
  • 配置序列化:ScriptableObject 和 JSON 两种序列化方式
  • 高级特性:自定义规则、资源标签、用户数据

通过深入理解 AssetBundleCollector 的源码实现,开发者可以更好地使用和扩展 YooAsset 的资源收集功能。


上一篇 :源码-编辑器总览 下一篇 :构建映射与依赖分析(BuildMap)

相关推荐
字节暗面3 小时前
客户端上报不可信:游戏服务端数据校验与对局重演设计
c#·游戏开发·服务端校验·反作弊
字节暗面3 小时前
游戏服务端如何校验客户端上报数据?四层校验思路详解
游戏开发
甲维斯17 小时前
我用AI做了一款「三国吃鸡」,开局孔明灯,落地青龙刀 !
人工智能·游戏·游戏开发
SmalBox20 小时前
04-01-源码-编辑器总览
unity3d·游戏开发
Behavior1 天前
Unity 7.0 Alpha 拆解:编辑器干掉 Mono 换 CoreCLR
c#·unity3d·游戏开发
SmalBox2 天前
03-06-架构篇-资源依赖与分组架构
unity3d·游戏开发
鑫鑫哥adam2 天前
一局游戏的时长,凭什么信客户端说的?
unity3d·游戏开发
Behavior2 天前
国内下载使用 Unity 6000 踩坑点总结
c#·unity3d·游戏开发
哈欠兽3 天前
Laya 1.x AS3 游戏开发 以玩家死亡为例子 了解如何通过事件调用函数
游戏开发