当前位置: 首页 > news >正文

05-08-YooAsset源码-Unity缓存系统与内存管理

源码-资源缓存机制

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


一、引言

本章将深入解析 YooAsset 资源缓存机制的源码实现。资源缓存是 YooAsset 资源管理的重要组成部分,通过缓存机制可以提高资源加载速度、减少网络请求。YooAsset 提供了多级缓存机制,包括内存缓存、磁盘缓存等。

资源缓存机制的设计目标是提供高效、可靠的缓存能力。本章将从源码层面深入解析 YooAsset 资源缓存机制的实现。


二、缓存机制概述

2.1 缓存的作用

缓存是资源管理的重要组成部分:

缓存的作用

  • 提高资源加载速度
  • 减少网络请求
  • 减少磁盘 I/O
  • 提升用户体验

缓存的类型

  • 内存缓存:AssetBundle 缓存
  • 磁盘缓存:文件缓存
  • 预加载缓存:预下载的资源

2.2 YooAsset 中的缓存

YooAsset 提供了多级缓存机制:

YooAsset 缓存体系 ├── 内存缓存 │ ├── BundleLoader 缓存 │ ├── Provider 缓存 │ └── AssetBundle 缓存 ├── 磁盘缓存 │ ├── 包内资源缓存(构建内) │ ├── 本地缓存(CacheSystem) │ └── 临时缓存 └── 预加载缓存 └── 预下载的资源

内存缓存详解

内存缓存是 AssetBundle 和 Provider 的内存缓存,提供最快的访问速度。

磁盘缓存详解

磁盘缓存是已下载资源的本地缓存,提供跨会话的持久化能力。

预加载缓存详解

预加载缓存是预下载的资源,可以在游戏空闲时预先加载。

2.3 缓存策略

YooAsset 提供了多种缓存策略:

缓存策略描述优点缺点
无缓存不缓存任何资源内存占用少加载慢
LRU最近最少使用自动清理复杂
容量限制限制缓存大小可控需要管理
手动缓存手动管理缓存灵活需要管理

无缓存策略详解

不缓存任何资源,每次都重新加载。适合内存紧张的小游戏。

LRU 策略详解

使用 LRU 算法自动清理最近最少使用的资源。

容量限制策略详解

限制缓存的总大小,避免内存溢出。

手动缓存策略详解

由开发者手动管理缓存,提供最大的灵活性。


三、BundleLoader 缓存

3.1 BundleLoader 缓存的作用

BundleLoader 缓存用于管理 AssetBundle 的加载:

BundleLoader 缓存的作用

  • 复用已加载的 AssetBundle
  • 避免重复加载
  • 提高加载速度

3.2 BundleLoader 缓存的实现

public class ResourceManager { private Dictionary<string, BundleLoader> _bundleLoaders = new Dictionary<string, BundleLoader>(); public BundleLoader LoadBundle(BundleInfo bundleInfo) { string key = bundleInfo.FileName; if (_bundleLoaders.TryGetValue(key, out var loader)) { loader.Retain(); return loader; } loader = new BundleLoader(bundleInfo, Package); loader.LoadAsync(); _bundleLoaders[key] = loader; loader.Retain(); return loader; } public void UnloadBundle(BundleLoader loader) { loader.Release(); if (loader.RefCount <= 0) { _bundleLoaders.Remove(loader.BundleInfo.FileName); } } }

缓存查询详解

通过 Bundle 文件名查询缓存。

缓存复用详解

缓存命中时复用 BundleLoader,并增加引用计数。

缓存清理详解

引用为 0 时清理 BundleLoader。

3.3 BundleLoader 缓存策略

public class ResourceManager { public void ClearAllBundles() { foreach (var loader in _bundleLoaders.Values) { loader.UnloadForce(); } _bundleLoaders.Clear(); } public void ClearUnusedBundles() { var unused = _bundleLoaders.Where(b => b.Value.RefCount == 0).ToList(); foreach (var kvp in unused) { kvp.Value.UnloadForce(); _bundleLoaders.Remove(kvp.Key); } } }

清除所有 Bundle 详解

ClearAllBundles 清除所有 Bundle,强制卸载所有 AssetBundle。

清除未使用 Bundle 详解

ClearUnusedBundles 清除未使用的 Bundle,保留正在使用的 Bundle。


四、Provider 缓存

4.1 Provider 缓存的作用

Provider 缓存用于管理已创建的 Provider:

Provider 缓存的作用

  • 复用已创建的 Provider
  • 减少 Provider 创建开销
  • 跟踪资源状态

4.2 Provider 缓存的实现

public class ResourceManager { private Dictionary<string, ProviderBase> _providerCache = new Dictionary<string, ProviderBase>(); public ProviderBase GetOrCreateProvider(string location, Type assetType) { string key = $"{location}_{assetType.Name}"; if (_providerCache.TryGetValue(key, out var provider)) { provider.IncreaseRefCount(); return provider; } provider = CreateProvider(location, assetType); _providerCache[key] = provider; provider.IncreaseRefCount(); return provider; } public void RemoveProvider(ProviderBase provider) { string key = $"{provider.Location}_{provider.AssetType.Name}"; _providerCache.Remove(key); } }

缓存 Key 生成详解

缓存 Key 由 location 和 assetType 组成。

Provider 复用详解

缓存命中时复用 Provider,增加引用计数。

Provider 销毁详解

引用为 0 时销毁 Provider。

4.3 Provider 缓存策略

public class ResourceManager { public void ClearAllAssets() { var providers = _providerCache.Values.ToList(); foreach (var provider in providers) { provider.UnProvide(); } _providerCache.Clear(); } public void ClearUnusedAssets() { var unused = _providerCache.Where(p => p.Value.RefCount == 0).ToList(); foreach (var kvp in unused) { kvp.Value.UnProvide(); _providerCache.Remove(kvp.Key); } } }

清除所有资源详解

ClearAllAssets 清除所有资源,强制销毁所有 Provider。

清除未使用资源详解

ClearUnusedAssets 清除未使用的资源,保留正在使用的资源。


五、磁盘缓存

5.1 磁盘缓存的作用

磁盘缓存用于持久化存储已下载的资源:

磁盘缓存的作用

  • 跨会话保存资源
  • 减少重复下载
  • 节省网络流量

5.2 磁盘缓存的位置

public class CacheSystem { private string _cacheRootPath; public CacheSystem() { // 缓存根目录 _cacheRootPath = Path.Combine(Application.persistentDataPath, "YooAsset/Cache"); if (!Directory.Exists(_cacheRootPath)) Directory.CreateDirectory(_cacheRootPath); } }

持久化路径详解

使用 Application.persistentDataPath 作为缓存根目录。

YooAsset/Cache 目录详解

在 persistentDataPath 下创建 YooAsset/Cache 目录用于缓存。

5.3 磁盘缓存的实现

public class CacheSystem { private Dictionary<string, FileInfo> _cachedFiles = new Dictionary<string, FileInfo>(); public bool IsCached(string fileName) { return _cachedFiles.ContainsKey(fileName); } public byte[] ReadCacheFile(string fileName) { string filePath = Path.Combine(_cacheRootPath, fileName); if (File.Exists(filePath)) return File.ReadAllBytes(filePath); return null; } public void WriteCacheFile(string fileName, byte[] data) { string filePath = Path.Combine(_cacheRootPath, fileName); File.WriteAllBytes(filePath, data); _cachedFiles[fileName] = new FileInfo(filePath); } public void RemoveCacheFile(string fileName) { string filePath = Path.Combine(_cacheRootPath, fileName); if (File.Exists(filePath)) File.Delete(filePath); _cachedFiles.Remove(fileName); } }

缓存查询详解

通过文件名查询缓存是否存在。

缓存读取详解

从缓存文件读取数据。

缓存写入详解

将数据写入缓存文件。

缓存删除详解

删除缓存文件。

5.4 磁盘缓存的清理

public class CacheSystem { public void ClearExpiredCache() { // 清理过期缓存 } public void ClearBySize(long maxSize) { // 按大小清理 } public void ClearByVersion(string currentVersion) { // 清理旧版本缓存 } }

过期清理详解

清理超过指定时间的缓存。

容量清理详解

限制缓存总大小,超出时清理最旧的缓存。

版本清理详解

清理旧版本的缓存,只保留当前版本的缓存。


六、内存缓存与磁盘缓存的配合

6.1 缓存配合的流程

缓存配合流程 1. 加载资源请求 2. 检查内存缓存(Provider、BundleLoader) 3. 内存缓存命中:直接返回 4. 内存缓存未命中:检查磁盘缓存 5. 磁盘缓存命中:加载到内存缓存 6. 磁盘缓存未命中:下载到磁盘缓存,再加载到内存缓存

内存缓存优先详解

优先检查内存缓存,提供最快的访问速度。

磁盘缓存次之详解

内存缓存未命中时,检查磁盘缓存。

下载最后详解

磁盘缓存未命中时,从远程下载。

6.2 缓存的实现

public class ResourcePackage { public AssetOperationHandle LoadAssetAsync(string location, Type assetType) { // 1. 检查内存缓存 var provider = ResourceManager.GetProvider(location, assetType); if (provider != null && provider.Status == EProviderStatus.Loaded) { return provider.GetHandle(); } // 2. 内存缓存未命中,加载资源 provider = ResourceManager.GetOrCreateProvider(location, assetType); provider.Provide(); return provider.GetHandle(); } }

内存缓存检查详解

优先检查内存缓存中是否已有 Provider。

加载资源详解

内存缓存未命中时,创建 Provider 并加载资源。

6.3 缓存的生命周期

内存缓存的生命周期

内存缓存在游戏会话内有效,游戏退出后自动释放。

磁盘缓存的生命周期

磁盘缓存跨会话有效,需要主动清理。

缓存与引用的关系

内存缓存与引用计数关联,引用为 0 时清理。


七、缓存优化

7.1 预加载

预加载是重要的缓存优化策略:

public class PreloadManager { public void PreloadAssets(List<string> locations) { foreach (var location in locations) { // 异步预加载 var handle = Package.LoadAssetAsync<GameObject>(location); } } }

预加载的作用详解

在游戏空闲时预先加载资源,避免游戏时加载卡顿。

预加载的应用场景详解

  • 游戏启动时预加载常用资源
  • 关卡切换时预加载下一关资源
  • 网络空闲时预加载未来资源

7.2 缓存预热

public class CacheWarmer { public void WarmCache(List<string> criticalResources) { foreach (var location in criticalResources) { var handle = Package.LoadAssetAsync<GameObject>(location); handle.Release(); // 预热后释放 } } }

缓存预热的作用详解

在游戏开始前预先加载关键资源到内存,避免第一次加载卡顿。

7.3 缓存监控

public class CacheMonitor { public CacheStatistics GetStatistics() { var stats = new CacheStatistics(); stats.MemoryCacheCount = ResourceManager.ProviderCache.Count; stats.MemoryCacheSize = CalculateMemoryCacheSize(); stats.DiskCacheCount = CacheSystem.CachedFileCount; stats.DiskCacheSize = CalculateDiskCacheSize(); return stats; } }

缓存监控的作用详解

监控缓存的使用情况,及时发现问题。


八、总结

本章深入解析了 YooAsset 资源缓存机制的源码实现,包括:

  • 缓存机制概述:缓存的作用、类型、策略
  • BundleLoader 缓存:BundleLoader 缓存的作用、实现、策略
  • Provider 缓存:Provider 缓存的作用、实现、策略
  • 磁盘缓存:磁盘缓存的作用、位置、实现、清理
  • 内存缓存与磁盘缓存的配合:配合流程、实现、生命周期
  • 缓存优化:预加载、缓存预热、缓存监控

通过深入理解资源缓存机制,开发者可以优化资源加载速度,提升游戏性能。


上一篇:引用计数机制
下一篇:文件系统体系(IFileSystem)

http://www.jsqmd.com/news/1208884/

相关文章:

  • GPT-5.6三档模型全线发布,Codex并入ChatGPT迈入Agent时代
  • 01 什么是量化金融?
  • 2026年7月最新北海防水补漏权威指南:卫生间/屋面/外墙/地下室正规施工+透明报价+避坑全攻略 - 吉林同城获客
  • FlashAttention技术解析:提升大模型训练效率的关键优化
  • 苹果M7 Ultra芯片:1.5TB统一内存如何重塑本地AI与高性能计算
  • UVa 684 Integral Determinant
  • 鸿蒙三方库 | harmony-utils之NetworkUtil默认网络与绑定网络详解
  • Linux包管理工具YUM核心机制与实战配置
  • 运放电路设计中电阻选型的核心要点与实战技巧
  • 2026年7月最新合肥积家官方售后服务热线与网点地址查询 - 积家官方售后服务中心
  • 如何用psd2fgui一键将PSD设计稿转换为FairyGUI资源包:游戏UI开发效率提升300%
  • 【iOS】离屏渲染
  • 企业自动化选型:RPA、Workflow、Agent到底有什么区别?——深度拆解企业级AI Agent与传统自动化的技术范式演进
  • 论文里的气象数据从哪来?揭秘高水平研究背后的“数据基础设施”
  • VMware安装操作系统KylinOS V10
  • 有质量的海报灯箱广告牌怎么选?实体店老板最关心的20个采购问题全解答 - 品牌报告
  • SAM 2模型解析:医疗影像分割实战与优化
  • 望友DFX软件赋能优特科技:破解人才断层与流程割裂,实现PCBA设计零缺陷
  • CH32X035芯片U盘固件更新方案与实现
  • Claude Code安装配置与核心功能实战指南:内置浏览器与智能代码补全
  • Kimi K2.6:用自然语言调度React+Three.js+Shader工程链路
  • AI智能体开发:Harness与Loop工程的核心差异与实践
  • 第二阶段:SPI 控制器注册
  • 微信里哪个小程序能免费去水印:实测几款工具的真实体验 - 科技热点发布
  • SpringBoot双重防御体系:SpringSecurity集成XSS与SQL注入协同防护实践
  • Stable Diffusion模型瘦身终极方案,单卡3090跑动12GB SDXL-LyCORIS模型(附量化精度损失对照表)
  • 抖音去水印在线工具推荐哪个好?免费多端实测对比 - 科技热点发布
  • 突破尼龙印花瓶颈:免模压起皱浆如何重构纺织特种工艺的降本逻辑
  • MyBatis-Plus字段自动加解密实践:无侵入保护敏感数据
  • 能跨系统操作的企业级自动化工具有哪些?不依赖API的那种 | 2026主流AI Agent与超自动化方案深度解析