05-04-YooAsset源码-Unity资源定位系统

源码-寻址系统

篇章:05-源码深度-运行时核心模块
阅读时间:约 25 分钟
前置知识:了解 ResourcePackage


一、引言

本章将深入解析 YooAsset 寻址系统的源码实现。寻址系统是 YooAsset 资源管理的核心,通过资源地址(Address)定位资源。YooAsset 支持 String Address、GUID Address、Label Address 三种寻址方式。深入理解寻址系统是掌握 YooAsset 资源定位机制的关键。

寻址系统的设计目标是提供灵活、可靠的资源定位能力。本章将从源码层面深入解析寻址系统的实现。


二、寻址系统概述

2.1 寻址的概念

寻址是通过资源地址(Address)定位资源的过程:

资源地址

资源地址是资源的唯一标识符,可以是字符串、GUID、Tag 等。

资源定位过程

  1. 用户传入资源地址
  2. YooAsset 在 Manifest 中查找地址
  3. 找到对应的 AssetInfo
  4. 根据 AssetInfo 加载资源

2.2 寻址方式

YooAsset 支持三种寻址方式:

寻址方式地址形式优点缺点
String Address字符串,如 "ui/login"易读、易记可能冲突
GUID AddressGUID,如 "a1b2c3d4"唯一、不冲突不可读
Label AddressTag,如 "ui"、"character"灵活、批量需要配置

2.3 寻址系统的架构

寻址系统架构 ├── AddressRule(寻址规则) │ ├── StringAddress │ ├── GuidAddress │ └── LabelAddress ├── AssetInfo(资源信息) │ ├── Address │ ├── AssetPath │ ├── AssetGUID │ ├── BundleID │ └── DependIDs └── BundleInfo(Bundle 信息) ├── BundleName ├── FileName ├── Dependencies └── ...

AddressRule 详解

AddressRule 定义了不同寻址方式的规则。

AssetInfo 详解

AssetInfo 是资源的信息类,包含了资源的所有元信息。

BundleInfo 详解

BundleInfo 是 Bundle 的信息类,包含了 Bundle 的所有元信息。


三、String Address 寻址

3.1 String Address 的概念

String Address 是最常用的寻址方式,使用字符串作为资源地址:

地址形式

字符串地址,类似于ui/logincharacters/hero

地址生成

地址在构建时生成,可以基于资源路径或自定义前缀生成。

地址示例

"ui/login" // UI 登录面板 "characters/hero" // 角色:英雄 "weapons/sword" // 武器:剑

3.2 String Address 的实现

public class AssetInfo { public string Address { get; set; } // 资源地址 public string AssetPath { get; set; } // 资源路径 public int BundleID { get; set; } // 所属 Bundle ID public int[] DependIDs { get; set; } // 依赖的 Bundle ID }

Address 字段详解

Address 是资源的地址字符串,运行时通过此地址定位资源。

AssetPath 字段详解

AssetPath 是资源在 Asset 目录中的路径。

BundleID 字段详解

BundleID 是资源所属 Bundle 的 ID,通过 BundleID 可以快速定位 Bundle。

3.3 字符串地址的解析

public class ResourcePackage { public AssetInfo GetAssetInfo(string location) { // 1. 直接在 AssetList 中查找 foreach (var asset in Manifest.AssetList.Assets) { if (asset.Address == location) return asset; } return null; } }

直接查找详解

字符串地址通过直接匹配查找。这种方式简单但效率较低,对于大量资源需要优化。

优化方案详解

YooAsset 内部使用 Dictionary 索引,提高查找效率。

private Dictionary<string, AssetInfo> _assetInfoDict; public AssetInfo GetAssetInfo(string location) { if (_assetInfoDict.TryGetValue(location, out var info)) return info; return null; }

四、GUID Address 寻址

4.1 GUID Address 的概念

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

GUID 的概念

GUID(Globally Unique Identifier)是 Unity 为每个资源生成的唯一标识符。

GUID 的生成

GUID 在资源导入时由 Unity 自动生成,存储在 .meta 文件中。

GUID 示例

"a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6"

4.2 GUID Address 的实现

public class ResourcePackage { public AssetInfo GetAssetInfoByGUID(string guid) { foreach (var asset in Manifest.AssetList.Assets) { if (asset.AssetGUID == guid) return asset; } return null; } }

GUID 查找详解

GUID 地址通过 AssetGUID 字段查找。GUID 是唯一的,不会有冲突。

GUID 的稳定性详解

GUID 在资源生命周期内保持稳定,不会因路径变化而变化。

4.3 GUID 的应用场景

资源重命名

资源重命名后,路径会变化,但 GUID 保持不变。使用 GUID 寻址可以避免资源重命名带来的问题。

资源移动

资源移动后,路径会变化,但 GUID 保持不变。使用 GUID 寻址可以避免资源移动带来的问题。

资源合并

合并多个资源时,使用 GUID 寻址可以保持引用关系的稳定。

4.4 GUID 的获取

public class GUIDHelper { public static string GetGUID(string assetPath) { return AssetDatabase.AssetPathToGUID(assetPath); } }

AssetDatabase.AssetPathToGUID 详解

使用 Unity 的 AssetDatabase.AssetPathToGUID API 获取资源的 GUID。

运行时使用详解

运行时,GUID 存储在 Manifest 中,开发者可以通过地址获取 GUID 并加载资源。


五、Label Address 寻址

5.1 Label Address 的概念

Label Address 使用资源标签(Tag)作为寻址方式:

Tag 的概念

Tag 是资源的标签,可以用于分类和批量访问。

Tag 的设置

Tag 在 Collector 中设置,或者在资源导入时设置。

Tag 示例

"ui" // UI 资源 "character" // 角色资源 "weapon" // 武器资源 "audio/bgm" // 音频:背景音乐

5.2 Label Address 的实现

public class AssetInfo { public string[] AssetTags { get; set; } // 资源标签 }

AssetTags 字段详解

AssetTags 是资源的标签数组,每个资源可以有多个标签。

Tag 匹配详解

通过 Tag 查找资源时,需要遍历所有资源,检查是否包含指定 Tag。

5.3 Label Address 的优化

public class ResourcePackage { private Dictionary<string, List<AssetInfo>> _tagIndex; public void BuildTagIndex() { _tagIndex = new Dictionary<string, List<AssetInfo>>(); foreach (var asset in Manifest.AssetList.Assets) { if (asset.AssetTags == null) continue; foreach (var tag in asset.AssetTags) { if (!_tagIndex.ContainsKey(tag)) _tagIndex[tag] = new List<AssetInfo>(); _tagIndex[tag].Add(asset); } } } public List<AssetInfo> GetAssetsByTag(string tag) { if (_tagIndex.TryGetValue(tag, out var assets)) return assets; return null; } }

Tag 索引详解

YooAsset 内部构建了 Tag 索引,可以快速通过 Tag 查找资源。

批量加载详解

通过 Tag 查找可以一次获取多个资源,便于批量加载。

5.4 Tag 的应用场景

批量加载

通过 Tag 批量加载资源,如LoadAssetsByTag("ui")加载所有 UI 资源。

资源分类

通过 Tag 对资源进行分类管理,便于查找和组织。

动态资源

通过 Tag 动态加载资源,如根据玩家等级加载不同等级的资源。


六、寻址系统的高级特性

6.1 多地址支持

一个资源可以有多个地址:

[CustomAddress("ui/login_panel")] [CustomAddress("ui/start/login")] public class LoginPanel : MonoBehaviour { // ... }

多地址优势详解

多地址可以让同一资源通过不同地址访问,便于集成不同的系统。

多地址实现详解

通过自定义特性实现多地址,资源可以被多个地址引用。

6.2 地址重定向

地址重定向允许将一个地址映射到另一个地址:

public class AddressRemapper { private Dictionary<string, string> _remap = new Dictionary<string, string>(); public void AddRemap(string source, string target) { _remap[source] = target; } public string Remap(string address) { if (_remap.TryGetValue(address, out var target)) return target; return address; } }

地址重定向的作用详解

地址重定向可以用于资源迁移、A/B 测试、版本切换等场景。

6.3 地址过滤

地址过滤可以在加载前对地址进行验证:

public class AddressValidator { public bool Validate(string address) { if (string.IsNullOrEmpty(address)) return false; if (address.Length > MaxLength) return false; // 其他验证 return true; } }

地址验证的作用详解

地址验证可以避免非法地址、过长地址等导致的加载失败。


七、Bundle 信息查询

7.1 BundleInfo 详解

BundleInfo 是 Bundle 的信息类:

public class BundleInfo { public int BundleID { get; set; } // Bundle ID public string BundleName { get; set; } // Bundle 名称 public string FileName { get; set; } // Bundle 文件名 public string FileHash { get; set; } // Bundle 文件 Hash public long FileSize { get; set; } // Bundle 文件大小 public string FileCRC { get; set; } // Bundle 文件 CRC public bool Encrypted { get; set; } // 是否加密 public EBundleType BundleType { get; set; } // Bundle 类型 public int[] DependIDs { get; set; } // 依赖的 Bundle ID }

BundleID 详解

BundleID 是 Bundle 的唯一标识符。

FileHash 详解

FileHash 是 Bundle 文件的 Hash,用于版本管理和完整性验证。

Encrypted 详解

Encrypted 标识 Bundle 是否加密。

7.2 资源到 Bundle 的映射

public class ResourcePackage { public BundleInfo GetBundleInfo(int bundleID) { foreach (var bundle in Manifest.BundleList.Bundles) { if (bundle.BundleID == bundleID) return bundle; } return null; } }

Bundle 查找详解

通过 BundleID 查找 Bundle。

Bundle 索引优化详解

使用 Dictionary 索引可以提高查找效率。


八、总结

本章深入解析了 YooAsset 寻址系统的源码实现,包括:

  • 寻址系统概述:寻址的概念、方式、架构
  • String Address 寻址:字符串地址的实现、解析、优化
  • GUID Address 寻址:GUID 地址的概念、实现、应用
  • Label Address 寻址:Tag 地址的概念、实现、索引
  • 寻址高级特性:多地址支持、地址重定向、地址过滤
  • Bundle 信息查询:BundleInfo、资源到 Bundle 的映射

通过深入理解寻址系统的实现,开发者可以更好地使用 YooAsset 的资源定位功能,并根据需要实现自定义的寻址策略。


上一篇:运行模式体系(PlayMode)
下一篇:资源提供者(Provider 体系)