05-02-源码-全局入口与包管理(YooAssets & ResourcePackage)

源码-全局入口与资源包(YooAssets & ResourcePackage)

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


一、引言

本章将深入解析 YooAsset 全局入口(YooAssets)与资源包(ResourcePackage)的源码实现。YooAssets 是 YooAsset 的全局静态入口,ResourcePackage 是资源管理的核心抽象。深入理解这两个类的实现,是掌握 YooAsset 资源管理的关键。

YooAssets 和 ResourcePackage 的设计体现了 YooAsset 的核心理念:清晰的职责划分、灵活的扩展能力、统一的 API 接口。本章将从源码层面深入解析这两个类的实现。


二、YooAssets 全局入口

2.1 YooAssets 的设计

YooAssets 是 YooAsset 的全局静态入口类:

csharp 复制代码
public static class YooAssets
{
    private static GameObject _operationUpdaterGo;
    private static readonly Dictionary<string, ResourcePackage> _packages = new Dictionary<string, ResourcePackage>();
    private static ResourcePackage _defaultPackage;
    
    public static ResourcePackage CreatePackage(string packageName);
    public static bool InitPackage(ResourcePackage package);
    public static void DestroyPackage(ResourcePackage package);
    public static ResourcePackage GetPackage(string packageName);
    public static void SetDefaultPackage(ResourcePackage package);
    public static ResourcePackage GetDefaultPackage();
}

核心字段详解:

  • _operationUpdaterGo:异步操作更新器的 GameObject
  • _packages:所有 Package 的字典
  • _defaultPackage:默认 Package

核心方法详解:

  • CreatePackage:创建 Package
  • InitPackage:初始化 Package
  • DestroyPackage:销毁 Package
  • GetPackage:获取 Package
  • SetDefaultPackage:设置默认 Package
  • GetDefaultPackage:获取默认 Package

2.2 YooAssets.CreatePackage

CreatePackage 方法创建 ResourcePackage:

csharp 复制代码
public static ResourcePackage CreatePackage(string packageName)
{
    if (_packages.ContainsKey(packageName))
    {
        Debug.LogError($"Package {packageName} already exists!");
        return _packages[packageName];
    }
    
    ResourcePackage package = new ResourcePackage(packageName);
    _packages.Add(packageName, package);
    return package;
}

重复创建保护详解:

CreatePackage 会检查是否已存在同名 Package,避免重复创建。

返回值详解:

CreatePackage 返回创建的 ResourcePackage 对象,开发者可以继续初始化。

2.3 YooAssets.InitPackage

InitPackage 方法初始化 ResourcePackage:

csharp 复制代码
public static bool InitPackage(ResourcePackage package)
{
    // 1. 启动 OperationUpdater
    if (_operationUpdaterGo == null)
    {
        _operationUpdaterGo = new GameObject("YooAssetOperationUpdater");
        _operationUpdaterGo.AddComponent<OperationUpdater>();
        UnityEngine.Object.DontDestroyOnLoad(_operationUpdaterGo);
    }
    
    // 2. 异步初始化 Package
    var operation = package.InitializeAsync();
    operation.Completed += (op) => {
        if (op.Status == EOperationStatus.Succeed)
        {
            Debug.Log($"Package {package.PackageName} initialized successfully");
        }
    };
    
    return true;
}

OperationUpdater 启动详解:

InitPackage 会确保 OperationUpdater GameObject 存在。OperationUpdater 负责在每帧更新异步操作。

异步初始化详解:

InitPackage 调用 package.InitializeAsync() 进行异步初始化。

完成回调详解:

初始化完成时,会触发回调通知,开发者可以监听此回调。

2.4 YooAssets.DestroyPackage

DestroyPackage 方法销毁 ResourcePackage:

csharp 复制代码
public static void DestroyPackage(ResourcePackage package)
{
    if (package == null) return;
    
    // 1. 销毁 Package
    package.Destroy();
    
    // 2. 从字典中移除
    _packages.Remove(package.PackageName);
    
    // 3. 如果是默认 Package,清空默认 Package
    if (_defaultPackage == package)
    {
        _defaultPackage = null;
    }
}

销毁顺序详解:

DestroyPackage 先销毁 Package,然后从字典中移除,最后清理默认 Package 引用。

注意事项详解:

DestroyPackage 是同步操作,会立即销毁 Package。开发者需要确保在销毁前没有正在进行的资源加载。

2.5 YooAssets 的辅助方法

csharp 复制代码
public static ResourcePackage GetPackage(string packageName)
{
    if (_packages.TryGetValue(packageName, out var package))
        return package;
    return null;
}

public static void SetDefaultPackage(ResourcePackage package)
{
    _defaultPackage = package;
}

public static ResourcePackage GetDefaultPackage()
{
    return _defaultPackage;
}

GetPackage 详解:

通过 packageName 获取 Package。

SetDefaultPackage 详解:

设置默认 Package。设置后,可以通过 ResourcePackage.DefaultPackage 加载资源。


三、ResourcePackage 资源包

3.1 ResourcePackage 的设计

ResourcePackage 是 YooAsset 资源管理的核心抽象:

csharp 复制代码
public class ResourcePackage
{
    public string PackageName { get; private set; }
    public PackageManifest Manifest { get; private set; }
    public IFileSystem BuildinFileSystem { get; private set; }
    public IFileSystem CacheFileSystem { get; private set; }
    public IFileSystem DeliveryFileSystem { get; private set; }
    public IPlayModeImpl PlayModeImpl { get; private set; }
    public ResourceManager ResourceManager { get; private set; }
    public DownloadManager DownloadManager { get; private set; }
    public CacheSystem CacheSystem { get; private set; }
    
    public InitializationOperation InitializeAsync(IBuildinQueryServices buildinQueryServices, IDeliveryQueryServices deliveryQueryServices);
    public UpdatePackageVersionOperation UpdatePackageVersionAsync();
    public UpdatePackageManifestOperation UpdatePackageManifestAsync();
    
    public AssetOperationHandle LoadAssetAsync<T>(string location);
    public SceneOperationHandle LoadSceneAsync(string location, LoadSceneMode sceneMode);
    public void UnloadAsset(AssetOperationHandle handle);
    public void Destroy();
}

核心字段详解:

  • PackageName:Package 名称
  • Manifest:Package 清单
  • BuildinFileSystem:构建内文件系统
  • CacheFileSystem:缓存文件系统
  • DeliveryFileSystem:远程文件系统
  • PlayModeImpl:运行模式实现
  • ResourceManager:资源管理器
  • DownloadManager:下载管理器
  • CacheSystem:缓存系统

3.2 ResourcePackage 初始化

ResourcePackage 初始化是 YooAsset 的核心流程:

csharp 复制代码
public InitializationOperation InitializeAsync(
    IBuildinQueryServices buildinQueryServices = null,
    IDeliveryQueryServices deliveryQueryServices = null)
{
    // 1. 加载 Manifest
    var loadManifestOp = LoadManifest();
    loadManifestOp.Completed += (op) => {
        if (op.Status == EOperationStatus.Succeed)
        {
            // 2. 初始化 FileSystem
            InitFileSystems(buildinQueryServices, deliveryQueryServices);
            
            // 3. 初始化 PlayMode
            InitPlayMode();
            
            // 4. 初始化 Manager
            InitManagers();
        }
    };
    
    return initializationOp;
}

加载 Manifest 详解:

首先加载 PackageManifest 文件,PackageManifest 包含了所有 Bundle 的信息。

初始化 FileSystem 详解:

根据运行模式初始化 FileSystem。Host 模式会同时初始化 BuildinFileSystem、CacheFileSystem、DeliveryFileSystem。

初始化 PlayMode 详解:

根据配置的运行模式创建对应的 PlayModeImpl。

初始化 Manager 详解:

初始化 ResourceManager、DownloadManager、CacheSystem 等管理器。

3.3 资源加载

ResourcePackage 提供了多种资源加载方法:

csharp 复制代码
public AssetOperationHandle LoadAssetAsync<T>(string location)
{
    return ResourceManager.LoadAssetAsync(location, typeof(T));
}

public SceneOperationHandle LoadSceneAsync(string location, LoadSceneMode sceneMode)
{
    return ResourceManager.LoadSceneAsync(location, sceneMode);
}

public SubAssetsOperationHandle LoadSubAssetsAsync<T>(string location)
{
    return ResourceManager.LoadSubAssetsAsync(location, typeof(T));
}

public RawFileOperationHandle LoadRawFileAsync(string location)
{
    return ResourceManager.LoadRawFileAsync(location);
}

LoadAssetAsync 详解:

异步加载指定类型的资源,返回 AssetOperationHandle。

LoadSceneAsync 详解:

异步加载场景,返回 SceneOperationHandle。

LoadSubAssetsAsync 详解:

异步加载子资源,返回 SubAssetsOperationHandle。

LoadRawFileAsync 详解:

异步加载原生文件,返回 RawFileOperationHandle。

3.4 资源卸载

ResourcePackage 提供了多种资源卸载方法:

csharp 复制代码
public void UnloadAsset(AssetOperationHandle handle)
{
    ResourceManager.UnloadAsset(handle);
}

public void UnloadScene(SceneOperationHandle handle)
{
    ResourceManager.UnloadScene(handle);
}

UnloadAsset 详解:

卸载资源。卸载时会减少 Provider 的引用计数,引用为 0 时销毁资源。

UnloadScene 详解:

卸载场景。

3.5 热更新

ResourcePackage 提供了热更新方法:

csharp 复制代码
public UpdatePackageVersionOperation UpdatePackageVersionAsync()
{
    return PlayModeImpl.UpdatePackageVersionAsync();
}

public UpdatePackageManifestOperation UpdatePackageManifestAsync()
{
    return PlayModeImpl.UpdatePackageManifestAsync();
}

UpdatePackageVersionAsync 详解:

更新 Package 版本。请求服务器的最新版本,与本地版本比较。

UpdatePackageManifestAsync 详解:

更新 Package Manifest。请求服务器的 Manifest,与本地 Manifest 比较,下载差异资源。

3.6 ResourcePackage 销毁

ResourcePackage 销毁时需要清理所有资源:

csharp 复制代码
public void Destroy()
{
    // 1. 销毁 Manager
    ResourceManager.Destroy();
    DownloadManager.Destroy();
    CacheSystem.Destroy();
    
    // 2. 销毁 FileSystem
    BuildinFileSystem?.OnDestroy();
    CacheFileSystem?.OnDestroy();
    DeliveryFileSystem?.OnDestroy();
    
    // 3. 销毁 PlayMode
    PlayModeImpl?.OnDestroy();
    
    // 4. 清空 Manifest
    Manifest = null;
}

销毁顺序详解:

销毁时按照 Manager → FileSystem → PlayMode → Manifest 的顺序进行销毁。

注意事项详解:

销毁 Package 前需要确保没有正在进行的资源加载,否则可能造成资源泄漏。


四、Manifest 处理

4.1 Manifest 加载

csharp 复制代码
private LoadManifestOperation LoadManifest()
{
    // 1. 获取 Manifest 文件路径
    string manifestFilePath = GetManifestFilePath();
    
    // 2. 异步加载 Manifest
    var loadOp = new LoadManifestOperation(manifestFilePath);
    loadOp.Start();
    
    return loadOp;
}

Manifest 文件路径详解:

Manifest 文件路径通常为 {BuildinPath}/{PackageName}/PackageManifest_{PackageVersion}.bytes。

异步加载详解:

使用 LoadManifestOperation 异步加载 Manifest 文件。

4.2 Manifest 解析

csharp 复制代码
private PackageManifest ParseManifest(byte[] manifestData)
{
    string json = System.Text.Encoding.UTF8.GetString(manifestData);
    return PackageManifest.FromJson(json);
}

JSON 解析详解:

将 Manifest 的字节数据转换为字符串,然后使用 JsonUtility 反序列化为 PackageManifest 对象。

4.3 Manifest 验证

csharp 复制代码
private bool ValidateManifest(PackageManifest manifest)
{
    if (manifest == null) return false;
    if (string.IsNullOrEmpty(manifest.PackageName)) return false;
    if (string.IsNullOrEmpty(manifest.PackageVersion)) return false;
    if (manifest.AssetList == null || manifest.AssetList.Assets == null) return false;
    if (manifest.BundleList == null || manifest.BundleList.Bundles == null) return false;
    return true;
}

验证项详解:

  • Manifest 不为空
  • PackageName 不为空
  • PackageVersion 不为空
  • AssetList 不为空
  • BundleList 不为空

五、版本管理

5.1 版本号

YooAsset 使用语义化版本号(Major.Minor.Patch):

csharp 复制代码
public string PackageVersion { get; set; }
public string ResourceVersion { get; set; }

PackageVersion 详解:

Package 的版本号。

ResourceVersion 详解:

资源的版本号,可以与 PackageVersion 不同。

5.2 版本检查

csharp 复制代码
public UpdatePackageVersionOperation UpdatePackageVersionAsync()
{
    // 1. 请求服务器版本
    var request = UnityWebRequest.Get(_versionURL);
    
    // 2. 解析服务器版本
    // 3. 与本地版本比较
    // 4. 返回最新版本
}

版本检查流程详解:

向服务器请求最新版本,解析后与本地版本比较。

5.3 版本更新

csharp 复制代码
public UpdatePackageManifestOperation UpdatePackageManifestAsync(string packageVersion)
{
    // 1. 加载服务器 Manifest
    // 2. 与本地 Manifest 对比
    // 3. 计算差异 Bundle
    // 4. 返回下载操作
}

版本更新流程详解:

根据 packageVersion 加载服务器的 Manifest,与本地 Manifest 对比,计算差异 Bundle,返回下载操作。


六、总结

本章深入解析了 YooAsset 全局入口(YooAssets)与资源包(ResourcePackage)的源码实现,包括:

  • YooAssets 全局入口:全局静态类的设计、CreatePackage、InitPackage、DestroyPackage 等方法
  • ResourcePackage 资源包:核心抽象、初始化、资源加载、卸载、热更新
  • Manifest 处理:加载、解析、验证
  • 版本管理:版本号、版本检查、版本更新

通过深入理解 YooAssets 和 ResourcePackage 的源码实现,开发者可以更好地使用 YooAsset 的资源管理功能,并根据自己的需求进行扩展。


上一篇 :运行时总览 下一篇 :运行模式体系(PlayMode)

相关推荐
SmalBox17 小时前
05-01-源码-运行时总览
unity3d·游戏开发
SmalBox2 天前
04-06-源码-调试与扫描工具
unity3d·游戏开发
RobinDevNotes3 天前
一套代码发布到十几个平台:Cocos入门速览
typescript·c#·游戏开发
应用市场3 天前
离线小游戏做“每日挑战”:日期当随机种子,整局存成 JSON,再加一个“我不是机器人”
android·kotlin·游戏开发
用户2788607285673 天前
战争雷霆换区记录:字段里的「未知」不能写成正常
网络协议·游戏开发
SmalBox3 天前
04-05-源码-清单生成与构建报告
unity3d·游戏开发
UWA4 天前
UGUI性能排查实战:隐藏血条后耗时下降,减少顶点为何没改善
ui·性能优化·cpu·游戏开发
SmalBox4 天前
04-04-源码-构建管线与任务系统
unity3d·游戏开发
应用市场5 天前
不用一张图片的像素小游戏:小人是字符串,房间是矩形,平衡靠两千个假玩家
android·kotlin·游戏开发