源码-寻址系统
篇章 :05-源码深度-运行时核心模块 阅读时间 :约 25 分钟 前置知识:了解 ResourcePackage
一、引言
本章将深入解析 YooAsset 寻址系统的源码实现。寻址系统是 YooAsset 资源管理的核心,通过资源地址(Address)定位资源。YooAsset 支持 String Address、GUID Address、Label Address 三种寻址方式。深入理解寻址系统是掌握 YooAsset 资源定位机制的关键。
寻址系统的设计目标是提供灵活、可靠的资源定位能力。本章将从源码层面深入解析寻址系统的实现。
二、寻址系统概述
2.1 寻址的概念
寻址是通过资源地址(Address)定位资源的过程:
资源地址:
资源地址是资源的唯一标识符,可以是字符串、GUID、Tag 等。
资源定位过程:
- 用户传入资源地址
- YooAsset 在 Manifest 中查找地址
- 找到对应的 AssetInfo
- 根据 AssetInfo 加载资源
2.2 寻址方式
YooAsset 支持三种寻址方式:
| 寻址方式 | 地址形式 | 优点 | 缺点 |
|---|---|---|---|
| String Address | 字符串,如 "ui/login" | 易读、易记 | 可能冲突 |
| GUID Address | GUID,如 "a1b2c3d4" | 唯一、不冲突 | 不可读 |
| Label Address | Tag,如 "ui"、"character" | 灵活、批量 | 需要配置 |
2.3 寻址系统的架构
css
寻址系统架构
├── 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/login、characters/hero。
地址生成:
地址在构建时生成,可以基于资源路径或自定义前缀生成。
地址示例:
csharp
"ui/login" // UI 登录面板
"characters/hero" // 角色:英雄
"weapons/sword" // 武器:剑
3.2 String Address 的实现
csharp
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 字符串地址的解析
csharp
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 索引,提高查找效率。
csharp
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 示例:
csharp
"a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6"
4.2 GUID Address 的实现
csharp
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 的获取
csharp
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 示例:
csharp
"ui" // UI 资源
"character" // 角色资源
"weapon" // 武器资源
"audio/bgm" // 音频:背景音乐
5.2 Label Address 的实现
csharp
public class AssetInfo
{
public string[] AssetTags { get; set; } // 资源标签
}
AssetTags 字段详解:
AssetTags 是资源的标签数组,每个资源可以有多个标签。
Tag 匹配详解:
通过 Tag 查找资源时,需要遍历所有资源,检查是否包含指定 Tag。
5.3 Label Address 的优化
csharp
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 多地址支持
一个资源可以有多个地址:
csharp
[CustomAddress("ui/login_panel")]
[CustomAddress("ui/start/login")]
public class LoginPanel : MonoBehaviour
{
// ...
}
多地址优势详解:
多地址可以让同一资源通过不同地址访问,便于集成不同的系统。
多地址实现详解:
通过自定义特性实现多地址,资源可以被多个地址引用。
6.2 地址重定向
地址重定向允许将一个地址映射到另一个地址:
csharp
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 地址过滤
地址过滤可以在加载前对地址进行验证:
csharp
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 的信息类:
csharp
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 的映射
csharp
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 体系)