阅前提示

该系列为Unity AddressableAssetSystem 学习笔记,记录源码阅读的理解。
适合人群:All
阅读方式:浏览
如描述有误请指教,如果对你有所帮助,点赞收藏吧:)

文章目录

  • 阅前提示
  • 简介
  • 组成
  • 生命周期
  • 资源加载的本质
  • 工作流程

官方文档

简介

Addressable Asset system 是Unity推出的新的资产管理加载打包的插件。它主打的特点在于:便捷

相较于传统的资产加载方式(Resources/AssetBundle),AddressableAssest拥有了完备的可视化编辑窗口以及内存管理。

  • VS Resources:不需要对资产路径要求的那么严格,做到了任何地方都可能加载。
  • VS AssetBundle:不需要复杂的准备过程,开发即用,并且不需要单独的进行内存管理,总结下来就是比较无脑。

其他关于Addressable的基础介绍这里就不再赘述了,作者在写这篇文章之前浏览了网上其他有关AddressableAsset的文章,发现存在很多关于此的基础介绍和简单使用,所以这里就不提了。接下来我们就从源码出发,好好看看AddressableAsset。


组成

Addressable Asset System,我把它的组成分为以下几个部分:

  • Manager

    • AddressablesImpl :AddressableAsset使用的接口本口
    • ResourceManager:管理资源
  • Operation
    • AsyncOperation :Addressable 核心异步操作流,一切的加载都源于其异步链式操作(AsyncOperation + ChainOperation)
    • ProviderOperation:资源加载操作,异步操作真正执行者,实现资源的异步加载。
  • Locator
    • ResourceLocationBase:资产定位的组成部分

这三个部分就包含了整个系统的所有脚本了,这里只列举了具有代表性的部分脚本,以便大家找到阅读源码的位置。

简单的来说,Addressable Asset System 的优势在于它统一了资源加载的入口与资源加载的方式。

可想而知,在使用Resources或者AssetBundle时我们关心的地方在哪?我们希望加载资源的Key是一致的,不希望它在情况A的时候要使用KeyA来加载,情况B的时候使用KeyB来加载,这很烦不利于资源的管理。

我们还要考虑加载方式,是同步加载还是异步加载Addressable 全都给你省了~


生命周期

初始化:

public AsyncOperationHandle<IResourceLocator> InitializeAsync(string runtimeDataPath, string providerSuffix = null, bool autoReleaseHandle = true)

m_InitializationOperation:初始化的异步操作处理
​ 添加各类Provider:ResourceManager.ResourceProviders.Add(...)

Update:

internal void Update(float unscaledDeltaTime)


资源加载的本质

 private AsyncOperationHandle ProvideResource(IResourceLocation location, Type desiredType = null){if (location == null)throw new ArgumentNullException("location");IResourceProvider provider = null;if (desiredType == null){provider = GetResourceProvider(desiredType, location);if (provider == null)return CreateCompletedOperation<object>(null, new UnknownResourceProviderException(location).Message);desiredType = provider.GetDefaultType(location);}IAsyncOperation op;int hash = location.Hash(desiredType);if (m_AssetOperationCache.TryGetValue(hash, out op)){op.IncrementReferenceCount();return new AsyncOperationHandle(op);}Type provType;if (!m_ProviderOperationTypeCache.TryGetValue(desiredType, out provType))m_ProviderOperationTypeCache.Add(desiredType, provType = typeof(ProviderOperation<>).MakeGenericType(new Type[] { desiredType }));op = CreateOperation<IAsyncOperation>(provType, provType.GetHashCode(), hash, m_ReleaseOpCached);// Calculate the hash of the dependenciesint depHash = location.DependencyHashCode;var depOp = location.HasDependencies ? ProvideResourceGroupCached(location.Dependencies, depHash, null, null) : default(AsyncOperationHandle<IList<AsyncOperationHandle>>);if (provider == null)provider = GetResourceProvider(desiredType, location);((IGenericProviderOperation)op).Init(this, provider, location, depOp);var handle = StartOperation(op, depOp);if (depOp.IsValid())depOp.Release();return handle;}

核心就是这一部分,返回 AsyncOperationHandle 用于做异步逻辑的节点触发。资源由ResourceProviderBase来完成加载,AsyncOperationBase 为 Provider 与 Handle的桥梁


工作流程

1.key -> IResourceProvider : 唯一路径 对应 IResourceProvider

2. ProvideResource :IResourceProvider 生成 AsyncOperationHandle

private AsyncOperationHandle ProvideResource(IResourceLocation location, Type desiredType = null)

细节:

  • provider 是执行资源加载的真正位置(继承ResourceProviderBase):根据location 数据获取对应的provider public IResourceProvider GetResourceProvider(Type t, IResourceLocation location)

  • op 是存放provider的操作流(ProviderOperation), 以 location.Hash为key -> m_AssetOperationCache

  • depOp 是依赖资源的加载操作

  • 根据 location 获取等到 provider

    provider = GetResourceProvider(desiredType, location);

  • op init 时绑定 provider

    ((IGenericProviderOperation)op).Init(this, provider, location, depOp);

  • 链式操作 执行 op.Execute

    var handle = StartOperation(op, depOp);

  • op.Execute 时进行provider的资源加载,并将自身绑定在ProvideHandle中

    m_Provider.Provide(new ProvideHandle(m_ResourceManager, this));

  • provider 资源加载完毕之后执行 ProvideHandle.Complete -> 即 op.ProviderCompleted :

    InternalOp.ProviderCompleted<T>(result, status, exception); result 就是加载的资源

  • 最终执行 AsyncOperationBase.Complete

3. StartOperation(operation,dependency) : 链式操作dependency若没完成则等待dependency结束

var handle = StartOperation(op, depOp);

        internal void Start(ResourceManager rm, AsyncOperationHandle dependency, DelegateList<float> updateCallbacks){...if (dependency.IsValid() && !dependency.IsDone)dependency.Completed += m_dependencyCompleteAction;elseInvokeExecute();}

**4. InvokeExecute : 执行Execute() 并在ResourceManager帧更新中添加回调 **

ResourceManager.m_UpdateCallbacks.Add(AsyncOperationBase.UpdateCallback)

ResourceManager.m_UpdateCallbacks 基于 MonoBehaviourCallbackHooks

5.ProviderOperation.Execute

        protected override void Execute(){...try{m_Provider.Provide(new ProvideHandle(m_ResourceManager, this));}catch (Exception e){ProviderCompleted(default(TObject), false, e);}}

执行各类Provider的Provide 进行资源加载,例如 AssetBundleProvider.Provide

m_RequestOperation = AssetBundle.LoadFromFileAsync(path, m_Options == null ? 0 : m_Options.Crc);
m_RequestOperation.completed += LocalRequestOperationCompleted;private void LocalRequestOperationCompleted(AsyncOperation op)
{m_AssetBundle = (op as AssetBundleCreateRequest).assetBundle;m_ProvideHandle.Complete(this, m_AssetBundle != null, null);
}InternalOp.ProviderCompleted<T>(result, status, exception);

.
.
.
.
.


嗨,我是作者Vin129,逐儿时之梦正在游戏制作的技术海洋中漂泊。知道的越多,不知道的也越多。希望我的文章对你有所帮助:)


AddressableAsset源码学习:组成与工作原理相关推荐

  1. 【Android 源码学习】SystemServer启动原理

    Android 源码学习 SystemServer启动原理 望舒课堂 SystemServer进程启动原理学习记录整理. 参考文章: Android系统启动流程(三)解析SyetemServer进程启 ...

  2. spring源码学习之整合Mybatis原理分析

    本文主要解析spring是如何与mybatis进行整合,整合的过程中需要哪些组件的支持.以前面提到过的配置例子<spring源码学习之aop事物标签解析> 整合的过程中需要使用以下这个依赖 ...

  3. 【Android 源码学习】Zygote启动原理

    Android 源码学习 Zygote启动原理 望舒课堂 Zygote进程启动原理学习记录整理. Zygote简介 Zygote是进程在init进程启动时创建的,进程本身是app_process,来源 ...

  4. (转)spring源码解析,spring工作原理

    转自:https://www.ibm.com/developerworks/cn/java/j-lo-spring-principle/ Spring 的骨骼架构 Spring 总共有十几个组件,但是 ...

  5. 从源码角度了解react工作原理

    为什么要用虚拟dom DOM操作很慢,轻微的操作都可能导致⻚面重新排版,非常耗性能.相对于DOM对象(dom对象打印出来很大,很难diff),js对象 处理起来更快,而且更简单.通过diff算法对比新 ...

  6. 从源码角度分析 Mybatis 工作原理

    作者:vivo互联网服务器团队-Zhang Peng 一.MyBatis 完整示例 这里,我将以一个入门级的示例来演示 MyBatis 是如何工作的. 注:本文后面章节中的原理.源码部分也将基于这个示 ...

  7. Go框架 gin 源码学习--路由的实现原理剖析

    往期回顾: gin源码解析 - gin 与 net/http 的关系 gin 源码解析 - 详解http请求在gin中的流转过程 上面两篇文章基本讲清楚了 Web Server 如何接收客户端请求,以 ...

  8. 医学影像信息系统(PACS源码)基本概况和工作原理

    一.医学影像信息系统(PACS)基本概况 医学影像信息系统(PACS)是一种集影像采集.传输.存储.管理.查询.诊断.报告.归档和科研于一体的综合性应用系统.它基于医学影像存储与通信系统(Pictur ...

  9. Android源码学习以及在工作中的应用01-TextView

    有人说种下一棵树最好的时间是十年前,其次是现在.我已经浪费了整整十年,所以从现在起,脚踏实地,静下心来学习,一切从头开始.期望十年后的自己,无怨无悔. 我们在自动化测试的工作中,有一个这样的场景需求. ...

最新文章

  1. springboot设置静态资源不拦截的方法
  2. 微众WeCross 跨链平台(1)平台介绍
  3. wxWidgets:实时传输时间RTTI
  4. 判断标签是否出界,重新设置样式
  5. 4项技巧使你不再为PHP中文编码苦恼
  6. UVA 1025 A Spy in the Metro DP水题
  7. [转载] 2020最新Java面试题,常见面试题及答案汇总
  8. 安卓之实现一个简单的电话拨号功能
  9. 软件项目失败的心理原因
  10. 奇安信代码安全实验室帮助谷歌修复 Chrome 沙箱外高危漏洞,获官方致谢
  11. 电视/电视盒点播APP软件系统定制开发方案
  12. android gc卡顿,由于频繁GC造成的界面卡顿原因分析
  13. 【软考软件评测师】第三十三章 数据库系统应用
  14. 后缀001,002,003等的文件解压
  15. 基于ROS1.0的stdr simulation搭建多移动机器人(multiple robots)仿真系统
  16. jersey java_Jersey 入门与Javabean
  17. 从原子结构,半导体,PN结到MOS管和CMOS
  18. C语言 输入一个华氏温度F,要求输出摄氏度C。
  19. Pytorch+LSTM+Attention 实现 Seq2Seq
  20. isnan函数返回值c语言,C++ std::isnan等函数的使用

热门文章

  1. 网传叮咚买菜大裁员?并非空穴来风
  2. ggplot2-设置坐标轴
  3. 第三章 软件需求分析
  4. 51单片机(ESP8266模块)
  5. pycharm快捷键记录
  6. 开环零极点对根轨迹的影响
  7. ConcurrentHashMap源码解读
  8. HTML页面为什么设置了UTF-8仍然中文乱码
  9. Java Web程序设计第12章课后第1题
  10. GitHub上开源了一个自制表情包项目