本章中将简要的描述如何使用Addressable
有两种办法可以将一个Unity中的资源标记为一可寻址的资源。
将资源拖动到对应分组后,Addressable会默认使用资源所在的位置为资源的唯一“地址”,比如:对于Assets/images/myImage.png资源,拖动到窗口中后,其名称依旧会是Assets/images/myImage.png。可以随时在窗口中对资源进行重新指定。
如果项目中是首次使用Addressable Asset System,当窗口被打开时,会提示创建一些配置数据或者加载旧的配置数据。默认情况下会在Assets目录下创建一个名为AddressableAssetsData,此目录中将会保存Addressable Asset System在编辑器模式及运行时需要的数据配置,如果您在使用版本管理工具,此目录中的内容需要被添加到版本管理中。
PS:不论是在属性面板中指定还是使用窗口,都要求“地址”必须是唯一的,因为在运行阶段,将会使用此“地址”做为资源加载的标识
Addressable Assets System需要将游戏中的资源构建到文件中,从而游戏在运行时才能加载与使用。资源的构建不是自动完成,您可以通过两种办法进行资源的构建:
AddressableAssetSettings.BuildPlayerContent()
您可以在游戏运行时使用Addressable提供的API进行加载或者实例化资源。Addressable加载资源时会将此资源依赖的所有的资源全部加载到内存中,对于需要实例化的(比如GameObject)加载到的资源,Addressable会对资源进行实例化后将其直接添加到场景中。
使用脚本加载资源的方法:
Addressables.LoadAssetAsync
or
Addressables.InstantiateAsync("AssetAddress");
PS:为何会有Loading与instantiating的区别,此处直接举例说明:在项目中使用Resources.Load("GameObjectPath")
后其实拿到的并不是对应的GameObject实例,而是Prefab中的配置数据,需要通过Instantiate过程才能得到真正的GameObject。Addressable提供上述的两种接口的原因也此一样。对于某些资源比如文本文件为何不需要Instantiate,而可以直接使用呢,请自行体会原因。
对于LoadAssetAsync
和InstantiateAsync
都是一个异步的操作,所以您需要指定一个回调来侦听资源是否加载完毕,使用接口加载资源会返回一个AsyncOperationHandle对象,通过此对象可以查看到更多的信息。
GameObject myGameObject;
...
Addressables.LoadAssetAsync<GameObject>("AssetAddress").Completed += OnLoadDone;
}
private void OnLoadDone(UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle<GameObject> obj)
{
// In a production environment, you should add exception handling to catch scenarios such as a null result;
myGameObject = obj.Result;
}
使用Addressable后需要使用特别的一种方法才能得到需要的子资源与组件对象。
对于组件(Component)来说
您只能通过load/instantiate后,得到组件所在的GameObject,然后通过GetComponent的方式才能得到需要的组件
对于子资源来说
Addressable提供一种特别的语法来进行子资源的加载,如果想从从一个Sprite Sheet中加载Sprites,或者从FBX中加载所有的Animation Clip,可以使用如下的语法:
Addressables.LoadAssetAsync
有时候可能希望Addressable中的资源像其它在MonoBehaviour中的字段一样能够在属性面板中进行指字,那么这种情况下使用AssetReference类可以解决此问题。
使用方式为:
在MonoBehaviour的脚本中添加字段public AssetReference explosion;
,添加后可以在属性面板中通过Addressable提供的下拉列表中选择对应的资源。
指定完成后,需要在脚本中使用对应的API进行加载或者Instaniate.如:
explosion.LoadAssetAsync
或者
explosion.InstantiateAsync(pos, rot);
对于AssetReference对象的LoadAssetAsync与InstantiateAsync方法同样是异步的,所以必须提供对应的回调。
Unity中存在着一些特殊的目录,StreamingAssets就是其中之一,如果不清楚的话,可以查阅Unity中特殊目录。
Addressable在构建资源的时,除了生成资源的AssetBundle外,还会生成一些数据文件,这些数据文件使得系统在运行时知道如何加载需要的资源。默认的情况下,构建的资源会临时放置于Library\com.unity.addressables
中,当构建整个游戏项目时,Addressable会自动根据当前的平台将构建的资源拷贝到StreamingAssets目录下,进行打包结束后,会自动删除添加的资源。采用这样的方式可以很方便处理不同平台发布版本时对资源的筛选,可以保证不会有无关的资源被打入包体内。
除了上述提到的数据文件外,其它的资源也会使用Library\com.unity.addressables
目录做为资源的存储位置,同时根据平台的不同会生成不同的目录,以用于区别不同平台下的资源。为了确保系统能够正常的运行,构建路径需要指定到[UnityEngine.AddressableAssets.Addressables.BuildPath]
中,同时加载工具需要指定{UnityEngine.AddressableAssets.Addressables.RuntimePath}
.
您可以调用Addressables.DownloadDependenciesAsync()
方法,以资源的“地址”或者标签为参数,进行依赖项资源的加载,一般情况下这些资源都是AssetBundle。
您可以通过调用方法后返回的AsyncOperationHandle
中的属性PercentComplete
来监听下载的进度。得知进度后,您可以添加一个进度条展示当前资源加载的进度。
如果您在进行资源下载前,需要征求用户的同意,可以调用Addressables.GetDownloadSize()
,可以您给定的“地址”或者标签对应的数据的大小(此方法会考虑目前在Unity缓存中已经下载的AssetBundle).
虽然提前下载资源是一件好事,但是某些情况下您可以不太希望这样做,比如:
除了提前下载外,您还可以选择部分内容进行预加载。您可以启动游戏后,开始在后台进行资源的下载,而不是展示一个界面,显示进度条来向用户展示当前正在加载的资源直到游戏全部加载结束才能进入游戏。当需要对应资源时,而这部分资源还在下载中,则可以显示一个等待或加载的界面,一直到需要的资源全部下载完成。(说的比较绕,其实就是平常说的边玩边下载的机制,一般会预加载必须的资源然后优先让用户进入游戏,在后台进行剩余资源的下载,如果遇到需要使用的资源在下载中,则需要等待资源下载完成,此过程中也应该根据资源的优先级不停的调整资源的下载顺序)
AssetBundle资源本身是与平台有关系的,Unity会自动处理不同平台间的差距,从而生成适合对应平台的AssetBundle,也因此造成了各个平台下的资源本身是无法共用的,您需要为每个需要发布的平台重新使用Addressable进行资源的构建。
默认的情况下,Addressable在构建资源时会根据给定的平台,在特定的目录下(默认是Library\com.unity.addressables
)创建对应平台的子目录,从而将生成的内容存储到此目录中。运行时也会根据当前的平台从对应的子目录中进行资源的加载。
需要注意的是: 如果在编辑器设置以打包的模式进行播放的话,Addressable将会根据当前的平台进行数据的加载,这也就意味着如果构建的资源与当前的平台不兼容的话,在播放时可能会出现很多异常的问题。
本文中的内容属于个人总结整理而来,个人水平有限,对于部分细节难免有理解错误及遗漏之处,如果您在阅读过程中有所发现,希望您能指正,同时文章中的部分内容也参考了其它大神的文章,如果文章中的内容侵犯了您的权益,表示非常歉意,请您指出,我将尽快修改。
如果您进行转载,请标明出处。
Addressable Asset System(可寻址资源系统)-第三章 开始使用(http://www.liyubin.com/articles/2019/08/08/1565262522616.html)