tap制造的两套独立的资源管理体系
精华03/2593 浏览开发日记 包含 AI 合成内容
资源管理体系说明
版本: v1.0.0
日期: 2026-03-25
适用范围: 全项目
1. 概述
本项目存在两套独立的资源管理体系,分别服务于不同的渲染层,两者不可混用、不可互相替代。第一套为引擎资源管线,服务3D场景层,管理Texture2D、Sound、Model等资源,由ResourceController管控;第二套为NanoVG图片句柄,服务2D UI层,管理NanoVG整数句柄,即nvgCreateImage返回值,由各UI模块自行管理。
2. 两套资源体系对比
引擎ResourceCache底层API为cache:GetResource(type, path),句柄类型是引擎C++托管的Resource对象,释放方式为cache:ReleaseResource(type, path),依赖全局cache,引擎启动即可使用,生命周期跟随引擎ResourceCache可延迟释放,引擎内部管理引用计数,支持cache:GetResourceAsync()异步加载,有ResourceController提供的自动淘汰机制,适用于3D场景相关模块,比如SceneView、WorldView等。NanoVG图片底层API为nvgCreateImage(vg, path, flags),句柄类型是int整数句柄,释放方式为nvgDeleteImage(vg, handle),依赖NanoVG实例的vg上下文,必须在nvgDelete(vg)之前释放,无引用计数需手动管理,仅支持同步加载,无自动淘汰机制,适用于NanoVG UI相关模块,比如GameUI、ShopPanel等。
3. ResourceController模块详解
3.1 基本信息文件路径为scripts/module/resource/ResourceController.lua,核心职责是在引擎ResourceCache之上,提供注册表驱动的资源加载、缓存、分组、优先级淘汰、占位降级功能,集成于GameController.lua即3D场景主控制器,初始化条件为config.resource.enabled ~= false时,由GameController自动初始化。
3.2 架构定位ResourceController并非直接加载资源的替代品,而是引擎cache之上的管理层,核心提供四大能力:一是注册表,所有资源先注册key、path、类型、优先级,再按key加载;二是分组加载,按场景/关卡分组批量异步加载,支持进度回调;三是优先级淘汰,内存超阈值时按优先级自动释放资源;四是降级占位,资源加载失败时,自动使用注册好的占位资源。其架构调用逻辑为GameController(3D场景主控)调用ResourceController.init(config)完成启动初始化,调用ResourceController.update(dt)实现每帧更新与定时内存检测,调用ResourceController.shutdown()实现停止时资源释放。
3.3 常量定义缓存优先级分为三级,PRIORITY_PERMANENT值为3,代表永不自动淘汰,适用于UI图标、常用BGM;PRIORITY_NORMAL值为2,代表内存紧张时可淘汰,适用于关卡资源;PRIORITY_TEMPORARY值为1,代表优先淘汰,适用于一次性语音、临时特效。资源分类分为四类,CATEGORY_IMAGE为图片/纹理,CATEGORY_AUDIO为音频,CATEGORY_MODEL为3D模型,CATEGORY_SCENE为场景。
3.4 完整API参考生命周期相关API:init(config?)用于初始化系统,config可配置内存警告阈值、检测间隔、自动淘汰开关;isEnabled()用于判断是否已初始化;update(dt)用于每帧调用,定时检测内存并触发淘汰;shutdown()用于释放所有注册资源,清空注册表并关闭系统。注册管理相关API:registerResource(key, opts)用于注册单个资源;registerBatch(entries)用于批量注册资源;registerGroup(group_name, keys)用于定义资源分组;registerFallback(res_type, path)用于注册某类型的占位降级资源。加载获取相关API:load(key)用于同步加载资源,失败则自动降级到占位资源;loadAsync(key, callback)用于异步加载资源;loadGroup(group, onProgress?, onComplete?)用于异步加载整个资源分组,支持进度与完成回调;getResource(key)用于获取已缓存资源,不触发加载;isLoaded(key)用于检查资源是否加载完成。释放相关API:release(key)用于释放单个资源;releaseGroup(group_name)用于释放整个分组资源;releaseByPriority(max_priority)用于批量释放指定优先级及以下的资源,返回释放数量。内存监控相关API:checkMemory()用于手动触发内存检测;getMemoryStats()用于返回内存统计数据,包含总内存、警告阈值、注册数量、加载数量等。
3.5 内存淘汰机制当cache:GetTotalMemoryUse()超过默认256MB的内存警告阈值时,自动执行三阶段淘汰:第一阶段释放所有PRIORITY_TEMPORARY优先级资源,若内存仍超标,第二阶段释放所有PRIORITY_NORMAL优先级资源,若依旧超标,第三阶段输出严重警告日志,PRIORITY_PERMANENT永久资源不会被自动淘汰。内存检测频率默认5秒一次,在update(dt)中累计计时触发。
3.6 占位降级机制资源加载失败时,自动切换为对应类型的占位资源,降级过程对用户透明,仅输出WARN级别的降级日志,不影响游戏正常运行。
3.7 内部数据结构注册表条目存储资源key、路径、类型、分类、优先级、加载状态等信息;分组表将多个资源key归入同一分组,方便批量管理;占位映射表存储不同资源类型对应的占位资源路径。
3.8 当前集成状态GameController.init()时调用ResourceController初始化,GameController.update(dt)时每帧调用其更新方法,GameController.stop()时调用其关闭方法。当前ResourceController仅服务3D场景层模块,NanoVG游戏逻辑模块与NanoVG UI模块均未使用该模块。
4. NanoVG图片管理现状
4.1 管理模式各NanoVG UI模块自行管理图片句柄,无统一管理层,分为两种管理模式。模式一为表缓存,适用于加载多张不确定图片的模块,通过表格缓存图片句柄,使用模块包括TaskPanel、ShopPanel、SignPanel、GachaPanel、InventoryPanel、GetPopup;模式二为单变量,适用于仅加载1-2张固定图片的模块,通过单个变量存储句柄,使用模块包括GameUI、main.lua。
4.2 持有NanoVG图片句柄的模块清单main.lua管理2张背景图,采用单变量模式;GameUI管理1张设置图标,采用单变量模式;ShopPanel、TaskPanel、SignPanel、GachaPanel、InventoryPanel、GetPopup均管理动态数量的图标,采用表缓存模式。
4.3 生命周期调用链模块停止或游戏重启时,统一调用各UI模块的cleanup(vg_)方法释放图片句柄,包括ShopPanel、TaskPanel、SignPanel等所有UI模块,main.lua自行释放背景图句柄,最后执行nvgDelete(vg_)销毁NanoVG上下文,确保图片句柄在上下文销毁前全部释放。
5. 复用性分析与结论
5.1 核心问题:ResourceController能否管理NanoVG图片?答案是不能,核心原因有四点。一是API层不同,ResourceController封装引擎资源操作API,NanoVG图片使用独立的创建与释放API,两者无法互通;二是上下文依赖,NanoVG图片操作需要vg上下文,ResourceController不持有也不应持有该上下文,其属于3D场景层模块;三是释放时序,NanoVG图片必须在上下文销毁前释放,ResourceController的关闭时序无法保证与之匹配;四是句柄类型不同,ResourceController管理Resource对象,NanoVG是整数句柄,无法纳入同一体系。
5.2 当前方案是否需要优化?当前阶段不需要,理由有四点:一是模块图片规模可控,总量不超过50个,手动管理可行;二是无跨模块共享图片,各模块图片路径互不重复,无重复加载问题;三是cleanup模式统一,所有模块遵循统一的释放约定,由main.lua统一调用;四是引入统一缓存会增加额外复杂度,需要额外做引用计数防止冲突。
6. 未来演进建议当出现以下场景时,需考虑提取统一的NvgImageCache模块:一是出现跨模块共享同一张图片的情况,需要引用计数与去重机制;二是NanoVG图片总量超过50张,需要LRU淘汰策略;三是需要统一的图片加载失败占位降级能力;四是大量图片同步加载导致卡顿,需要分帧或预加载调度。
变更记录
版本v1.0.0,
日期2026-03-25,
初版内容包含ResourceController模块详解、NanoVG图片管理现状、复用性分析与未来演进建议



