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

KEngine:Unity3D资源的打包、加载、调试监控

资源模块做什么?

资源模块——ResourceModule,是KEngine中最核心的模块,其他模块基本或多或少的对它有依赖,它主要的功能是:资源打包、路径定义、资源管理、资源调试

资源模块对Unity的Asset Bundle接口进行了完整的封装,运行模式下可以使用它进行完整的资源加载、卸载,也可以通过它方便地查找资源内存泄露的问题。

AssetBundle自动化打包

Unity 5中,Asset Bundle系统做了很大的变化。你只需将需要打包的资源配置AssetBundle Name,然后执行接口BuildPipeline.BuildAssetBundles(outputPath)就完成了所有AssetBundle的打包,比Unity 4.x方便多了。

1835687-f321afec78c28857

图:把需要打包的资源放到BundleResources目录中

 

1835687-3dc5b149ffbe865a

图:AssetBundle最终默认生成到Product/Bundles/(Platform)/中

 

1835687-017b666adb7a1b54

图:KEngine->AssetBundle->Build All,自动设置BundleResources目录下所有的资源的Asset Bundle Name并执行打包

 

在KEngine+Unity 5.x中,把配置AssetBundle Name的这一步也省掉了。你只需把需要打包的资源,放在Assets/BundleResources目录中,所有的AssetBundle将会完整导出。

路径定义

Unity跨平台开发中,针对不同的平台——如编辑器、安卓、IOS、Windows等,一般有不同的资源存放路径。

像生成的Asset Bundle,还需要针对不同的平台,生成完全不一样的Asset Bundle资源。

因而KEngine中分别对Unity中的StreamingAssetsPath、PersistentDataPath等做了封装,开发人员无需为资源放在什么目录进行烦恼了(详见ResourceModule中的InitResourcePath方法),并且,内置了支持热更新。

举例:加载一个Asset Bundle的路径选择

假设现在要加载一个UI资源"Login":

public IEnumerator LoadUIAsset(CUILoadState loadState, UILoadRequest request)
{
    string path = string.Format("ui/login.prefab.bytes"));
    var assetLoader = KStaticAssetLoader.Load(path);
    while (!assetLoader.IsCompleted)
        yield return null;

    request.Asset = assetLoader.TheAsset;  // Asset 是GameObject
}

这个StaticAssetLoader,做了什么操作?假设我们在Android平台

  • 获知ui/login.prefab.bytes这个路径
  • 寻找热更新资源,尝试加载PersistentAssetsPath/Bundles/Android/ui/logins.prefabs.bytes
  • 无法找到热更新资源,尝试加载StreamingAssetsPath/Bundles/Android/ui/logins.prefabs.bytes
  • 依然无法找到,加载失败

资源加载

KEngine在Unity 5.x中,会自动的先加载依赖资源,你只要填入Asset Bundle的路径名字就可以了。就像Unity的Resources类一样。

简单加载

使用ResourceModule中的LoadBundleLoadBundleAsync接口,可以实现类似于Unity的Resources.LoadResources.LoadAsync的效用。

要注意的是,LoadBundle、LoadBundleAsync接口,起始地址是加载StreamingAssets/Bundles/Win32或StreamingAssets/Bundles/Android这种平台相关的路径。

// 同步加载,返回加载器,加载器中有加载的资源
var reqeust = ResourceModule.LoadBundle("ui/login.prefab.bytes")
Debug.Log(request.Asset != null); // true

// 异步加载,返回加载器,加载器中还没加载的资源,需要异步等待
var request = ResourceModule.LoadBundleAsync("ui/login.prefab.bytes", (isOk, asset, args)=>{});
Debug.Log(request.Asset == null); // true

Loader加载器

KEngine中定义了各种类型的资源加载器,提供更为方便的加载、调试功能,来避免一些使用上的。坑

Loader加载器

加载GameObject

最常用的Loader有两个:

  • StaticAsset:每次调用Load,使用同一份GameObject引用
  • InstanceAsset:每次调用Load,都会拷贝出一份GameObject
// 协程风格
public IEnumerator LoadUIAsset(UILoadRequest request)
{
    string path = string.Format("ui/login.prefab.bytes"));
    var assetLoader = KStaticAssetLoader.Load(path);
    while (!assetLoader.IsCompleted)
        yield return null;

    request.Asset = assetLoader.TheAsset;  // Asset 是GameObject
}
// CPS回调风格
public void LoadUIAsset(UILoadRequest request)
{
    string path = string.Format("ui/login.prefab.bytes"));
    KStaticAssetLoader.Load(path, (isOk, asset, args)=>{
        request.Asset =asset; 
    });
}

资源的释放

KEngine中的资源释放,跟Unity的资源释放明显区别是:Unity中提供Resources.UnloadUnusedAssets接口,来自动释放无用的资源的。而KEngine中资源释放采用纯手动的方式。

这主要是因为躺过Unity自动释放资源的很多坑: 经常会遇到“missing”的资源引用吧?因此选择了手动释放机制。

所有XXXLoader,都有一个接口Loader.Release(),举例:

string path = string.Format("ui/login.prefab.bytes"));
var assetLoader = KStaticAssetLoader.Load(path);  // 引用计数1
while (!assetLoader.IsCompleted)
    yield return null;
var assetLoader2 = KStaticAssetLoader.Load(path);  // 引用计数2
while (!assetLoader2.IsCompleted)
    yield return null;

assetLoader2.Release(); // 释放,减小引用计数  // 引用计数1
assetLoader.Release(); // 引用计数0,正式删掉缓存的资源

手工释放的资源存在引用计数,只有当引用计数为0,Loader才会触发回收,并且连同加载过的AssetBundle彻底消灭,节省内存。

其它Loader

诸如TextureLoader、AudioLoader等等,所有XXXLoader的使用方法都是一致的,它们提供CPS回调风格和协程风格

资源的调试监控

在Unity Editor模式下,所有的XXXLoader加载类实例,都会伴随住一个GameObject的产生,而这个GameObject,只用于进行调试、内存信息查看:

1835687-d3ce2681c5d480ee

图:资源加载调试信息:Loader、加载的对象

 

1835687-da5e24f6ff4801ec

图:每一个Loader的引用计数信息,都可以通过面板来进行实时查看

 

如上图所示,通过KEngine的资源调试器,可以方便的找到加载的AssetBundle的资源对象、监控内存占用的大小、Loader加载消耗的时间、Loader当前引用计数等信息。对比Unity原生的Profiler,这些信息是即时的。 开发人员可以非常方便的寻找资源泄露问题,优化内存占用。

 

版权说明

文/公的Kelly[mr-kelly](简书作者)     Email: 23110388@qq.com
原文链接:http://www.jianshu.com/p/ce3b5d0bdf8c
著作权归作者所有,转载请联系作者获得授权,,并标注“简书作者”。

 

KSFramework系列

github地址:https://github.com/mr-kelly/KSFramework

欢迎大家到 github提issues

 

KSFramework(集成U3D热重载)README

KSFramework:Unity3D开发框架快速入门

KEngine策划指南:配置表格的编辑与编译

相关文章:

  • 用idea打包spring boot项目,然后部署到Linux服务器上
  • linux 下查看机器是cpu是几核的(转)
  • 阿里巴巴 Java 开发手册--学习(一)
  • zookeeper监控软件
  • 阿里巴巴 Java 开发手册--学习(二)
  • PTPX中的activity文件以及mapping文件
  • 阿里巴巴 Java 开发手册--学习(三)
  • 阿里巴巴 Java 开发手册--学习(四)
  • Selenium入门之元素的基本定位以及操作
  • 阿里规约插件的安装和使用
  • Tomcat结构及处理请求过程
  • Spark Rdd coalesce()方法和repartition()方法
  • 基于Oracle的SQL优化--学习(一)
  • 基于Oracle的SQL优化--学习(二)
  • MySQL案例-show fileds from 提示无权限
  • CAP 一致性协议及应用解析
  • Docker: 容器互访的三种方式
  • Gradle 5.0 正式版发布
  • Java编程基础24——递归练习
  • Linux后台研发超实用命令总结
  • redis学习笔记(三):列表、集合、有序集合
  • spark本地环境的搭建到运行第一个spark程序
  • use Google search engine
  • VUE es6技巧写法(持续更新中~~~)
  • Zepto.js源码学习之二
  • 对JS继承的一点思考
  • 每天10道Java面试题,跟我走,offer有!
  • 使用Envoy 作Sidecar Proxy的微服务模式-4.Prometheus的指标收集
  • #Linux(帮助手册)
  • #pragma multi_compile #pragma shader_feature
  • #我与Java虚拟机的故事#连载12:一本书带我深入Java领域
  • $refs 、$nextTic、动态组件、name的使用
  • ( 10 )MySQL中的外键
  • (备忘)Java Map 遍历
  • (笔试题)分解质因式
  • (亲测成功)在centos7.5上安装kvm,通过VNC远程连接并创建多台ubuntu虚拟机(ubuntu server版本)...
  • (详细版)Vary: Scaling up the Vision Vocabulary for Large Vision-Language Models
  • (转)Groupon前传:从10个月的失败作品修改,1个月找到成功
  • (转)一些感悟
  • * 论文笔记 【Wide Deep Learning for Recommender Systems】
  • ... fatal error LINK1120:1个无法解析的外部命令 的解决办法
  • .helper勒索病毒的最新威胁:如何恢复您的数据?
  • .NET 4.0网络开发入门之旅-- 我在“网” 中央(下)
  • .net core webapi 大文件上传到wwwroot文件夹
  • .NET 将混合了多个不同平台(Windows Mac Linux)的文件 目录的路径格式化成同一个平台下的路径
  • .net通用权限框架B/S (三)--MODEL层(2)
  • .NET中 MVC 工厂模式浅析
  • /ThinkPHP/Library/Think/Storage/Driver/File.class.php  LINE: 48
  • [145] 二叉树的后序遍历 js
  • [AIGC codze] Kafka 的 rebalance 机制
  • [Angular] 笔记 16:模板驱动表单 - 选择框与选项
  • [AutoSar]工程中的cpuload陷阱(三)测试
  • [C# 基础知识系列]专题十六:Linq介绍
  • [C++]:for循环for(int num : nums)
  • [Contiki系列论文之2]WSN的自适应通信架构