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 Dictionarystring, BundleLoader _bundleLoaders new Dictionarystring, 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 缓存用于管理已创建的 ProviderProvider 缓存的作用复用已创建的 Provider减少 Provider 创建开销跟踪资源状态4.2 Provider 缓存的实现public class ResourceManager { private Dictionarystring, ProviderBase _providerCache new Dictionarystring, 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 Dictionarystring, FileInfo _cachedFiles new Dictionarystring, 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(Liststring locations) { foreach (var location in locations) { // 异步预加载 var handle Package.LoadAssetAsyncGameObject(location); } } }预加载的作用详解在游戏空闲时预先加载资源避免游戏时加载卡顿。预加载的应用场景详解游戏启动时预加载常用资源关卡切换时预加载下一关资源网络空闲时预加载未来资源7.2 缓存预热public class CacheWarmer { public void WarmCache(Liststring criticalResources) { foreach (var location in criticalResources) { var handle Package.LoadAssetAsyncGameObject(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

相关新闻

Creo二次开发实战:MCADExTools安装配置与阶梯剖视图自动化

Creo二次开发实战:MCADExTools安装配置与阶梯剖视图自动化

1. 项目概述:MCADExTools 是什么,为什么值得花时间装它MCADExTools 这个名字在 Creo 用户圈里不算陌生,但真正搞清楚它到底能干什么、值不值得为它折腾安装流程的人,其实不多。我第一次听说它,是在帮一家做精密齿轮箱的…

2026/7/17 20:44:31阅读更多 →
Loop窗口管理工具:5个实用技巧让Mac桌面工作流更高效

Loop窗口管理工具:5个实用技巧让Mac桌面工作流更高效

Loop窗口管理工具:5个实用技巧让Mac桌面工作流更高效 【免费下载链接】Loop Window management made elegant. 项目地址: https://gitcode.com/GitHub_Trending/lo/Loop Loop是一款优雅的macOS窗口管理工具,通过直观的径向菜单系统和丰富的自定义…

2026/7/17 20:39:30阅读更多 →
Linux YUM包管理器核心命令与实战技巧

Linux YUM包管理器核心命令与实战技巧

1. YUM包管理器概述在Red Hat系Linux发行版中,yum(Yellowdog Updater Modified)作为经典的RPM包管理前端工具,至今仍在CentOS 7及以下版本中广泛使用。这个基于Python开发的工具通过自动解决依赖关系,彻底改变了早期需…

2026/7/17 20:39:30阅读更多 →
WS51单片机ISP下载速度优化:从4.8kbps到25.6kbps实战指南

WS51单片机ISP下载速度优化:从4.8kbps到25.6kbps实战指南

如果你正在使用WS51系列单片机进行开发,可能会遇到一个共同的痛点:ISP下载速度太慢。传统的ISP下载程序往往只有几kbps的速度,每次烧录程序都需要等待几十秒甚至更长时间,这在快速迭代的开发过程中简直是效率杀手。最近&#xff0…

2026/7/17 21:49:36阅读更多 →
JavaScript性能优化:提升Web应用效率的关键策略

JavaScript性能优化:提升Web应用效率的关键策略

1. JavaScript性能优化的重要性在Web开发领域,性能优化始终是开发者面临的核心挑战之一。随着前端应用变得越来越复杂,JavaScript代码的执行效率直接影响着用户体验。一个加载缓慢、交互卡顿的网页会让用户迅速失去耐心,导致跳出率上升和转化…

2026/7/17 21:49:36阅读更多 →
OpenCV计算机视觉实战:从图像处理到文档识别

OpenCV计算机视觉实战:从图像处理到文档识别

1. 项目概述:OpenCV在计算机视觉中的核心价值OpenCV(Open Source Computer Vision Library)作为计算机视觉领域最广泛使用的开源库,已经成为图像处理和信息识别的基础设施。这个跨平台的计算机视觉库最初由Intel开发,如…

2026/7/17 21:49:36阅读更多 →
deepcode-cli:终端AI编程助手实战指南与效率优化

deepcode-cli:终端AI编程助手实战指南与效率优化

1. 先搞清楚它到底解决什么实际问题如果你经常在终端里写代码、改配置、排查问题,可能会遇到这种情况:需要快速写一段脚本,但记不清某个命令的参数;或者想优化一个复杂函数,但不确定哪种写法更高效。这时候如果还要切到…

2026/7/17 21:49:36阅读更多 →
Sol Ultra项目:计算辅助证明解决Erdős图论难题的技术解析

Sol Ultra项目:计算辅助证明解决Erdős图论难题的技术解析

这次我们来看一个数学领域的突破性进展——Sol Ultra 项目成功解决了著名的 Erdős 问题 #793。这个项目不是传统的软件工具或AI模型,而是数学证明领域的重要成果,对于理解组合数学和图论中的基础问题具有重要意义。Erdős 问题是以著名数学家保罗Erdős…

2026/7/17 21:49:36阅读更多 →
TicketFlow AI 项目实践(六):模型压缩、LLM 分类与 Flask 部署

TicketFlow AI 项目实践(六):模型压缩、LLM 分类与 Flask 部署

完成BERT微调后,项目继续探索模型压缩、大模型分类和服务化。本篇是TicketFlow AI系列的工程落地总结。 一、为什么需要模型压缩 BERT模型语义能力较强,但权重较大、CPU推理成本较高。项目分别实现动态量化、非结构化剪枝和知识蒸馏,比较模…

2026/7/17 21:44:35阅读更多 →
VSCode TypeScript 环境配置对比:全局安装 vs 项目本地安装的4个关键差异

VSCode TypeScript 环境配置对比:全局安装 vs 项目本地安装的4个关键差异

VSCode TypeScript 环境配置对比:全局安装 vs 项目本地安装的4个关键差异当你在VSCode中启动一个新的TypeScript项目时,第一个技术决策往往从安装方式开始。这个看似简单的选择——全局安装还是项目本地安装——实际上会深刻影响你的开发流程、团队协作和…

2026/7/17 10:42:55阅读更多 →
智慧树刷课插件:5分钟实现自动化学习的智能助手

智慧树刷课插件:5分钟实现自动化学习的智能助手

智慧树刷课插件:5分钟实现自动化学习的智能助手 【免费下载链接】zhihuishu 智慧树刷课插件,自动播放下一集、1.5倍速度、无声 项目地址: https://gitcode.com/gh_mirrors/zh/zhihuishu 智慧树刷课插件是一款专为智慧树在线教育平台设计的Chrome浏…

2026/7/17 8:31:03阅读更多 →
Steam创意工坊下载器WorkshopDL:跨平台游戏模组获取的终极解决方案

Steam创意工坊下载器WorkshopDL:跨平台游戏模组获取的终极解决方案

Steam创意工坊下载器WorkshopDL:跨平台游戏模组获取的终极解决方案 【免费下载链接】WorkshopDL WorkshopDL - The Best Steam Workshop Downloader 项目地址: https://gitcode.com/gh_mirrors/wo/WorkshopDL 你是否在GOG或Epic Games Store购买了心仪的游戏…

2026/7/17 13:22:23阅读更多 →
VS Code 高效配置与个性化定制全攻略

VS Code 高效配置与个性化定制全攻略

1. VS Code 高效配置基础作为一款轻量级但功能强大的代码编辑器,VS Code 的默认配置已经能满足基本需求,但通过合理调整设置可以大幅提升编码效率。我使用 VS Code 已经有五年多时间,期间尝试过各种配置方案,总结出这套适合大多数…

2026/7/17 0:00:01阅读更多 →
从竞赛代码到桌面工具:让 SuperADD 与 SubspaceAD 真正跑进自己的图像

从竞赛代码到桌面工具:让 SuperADD 与 SubspaceAD 真正跑进自己的图像

在异常检测领域,很多优秀算法最初都是以研究代码的形式发布的。它们能够在固定测试集上复现实验结果,却不一定能被普通用户直接拿来测试自己的图片。尤其是最近很多算法仅提供在固定测试集的测试环境,而gradio的demo演示也不会提供。 对工程应用和在自己的图片上进行测试来…

2026/7/17 0:00:01阅读更多 →
WinRAR高效配置指南:从基础安装到高级压缩实战

WinRAR高效配置指南:从基础安装到高级压缩实战

前几天帮同事处理一个客户发来的压缩包,解压时系统自带的工具弹出一串乱码,换用 WinRAR 却顺利打开了。这种看似简单的场景,恰恰暴露了不同压缩工具在处理非标准编码、分卷压缩或加密文件时的差异。WinRAR 作为一款老牌工具,真正价…

2026/7/17 0:00:01阅读更多 →
YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

如果你在部署 YOLOv8 时,发现推理速度只有可怜的 1-2 FPS,而别人的演示视频却能跑到 30 FPS 以上,那么问题很可能不在模型本身,而在于你的整个处理链路。很多开发者拿到一个训练好的 YOLOv8 模型后,会直接使用官方示例…

2026/7/16 20:13:14阅读更多 →
Coze与Dify对比指南:低代码AI应用开发从入门到实战

Coze与Dify对比指南:低代码AI应用开发从入门到实战

1. 从零到一:为什么你需要了解 Coze 和 Dify?如果你对 AI 应用开发感兴趣,但一看到“大模型”、“智能体”、“工作流”这些词就头疼,觉得门槛太高,那这篇文章就是为你准备的。很多开发者,包括我自己&#…

2026/7/17 13:22:38阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

AI生图工具怎么选?2026年6月版实测对比

做自媒体的朋友应该都有体会:配图一直是个让人头疼的问题。2026年,AI生图工具已经非常成熟了,但工具太多反而不知道怎么选。以下是截至2026年6月我对主流AI生图工具的实测对比。Midjourney V8.1:速度之王2026年6月11日&#xff0c…

2026/7/17 17:26:50阅读更多 →