Unity干货unity3d

Addressable Asset System(进阶版AB)和

2019-11-27  本文已影响0人  陌路契约zzz

介绍

打包对比

AB打包方式

AB文件是一个存档,在内部包含多个文件。此存档的结构可能会略有变化,具体取决于它是普通AB还是场景AB。这是普通AB的结构:


img

场景AB与普通的AB不同,因为它已针对场景及其内容的流加载进行了优化。


image.png
Addressable打包方式

加载资源对比

AB加载方式

我们用AB来加载资源的过程中,主要包含两个过程,第一步是先要加载本地或者网络上的AB资产包,再通过操作这个AB来加载它里面所包含的资源。

Addressable加载方式

我们首先把资源标记为可寻址,可寻址资源系统会给我们一个它的地址,然后我们可以根据这个地址去异步加载资源。可寻址资源系统的加载资源方式都是异步的,所以我们需要监听它加载完成再使用。

卸载资源方式对比

AB卸载方式

1574582786621.png

该图可以清晰的描述AB加载后的内存分布和不同的卸载方式对应卸载哪一些区域。

Addressable卸载方式

由于Addressable是在AB的基础上使用的系统,所以它的内存分布跟AB差不多,但是由于我们不能拿到资源对应的ab对象,只能通过Addressable给出的接口释放资源。Addressable内部已经给我们做了引用计数管理,所有当我们释放对应资源时,只有当引用计数为0才会真正的卸载对应ab对象。

热更资源方式对比

AB热更资源方式

热更资源在Addressable推出之前每个项目都有自己的做法,但是大致上都可以抽象为以下流程。

Addressable热更资源方式

Addressable也支持资源热更,但是还是有很多不足的地方。我用了它的热更功能然后看了它热更功能的实现后发现它更加适合边下边玩,而不是在游戏刚进去时更新完所有资源。原因有以下几点:

虽然它本身不支持游戏初始化时下载所有资源,但是因为addressable是开源的,我们可以直接修改源码来达到我们自己想要的效果。比如我们想在游戏刚开始得到所有需要更新ab的大小,我们可以通过以下代码来实现

AddressablesImpl.cs
//添加2个新方法
//初始化完之后调用GetRemoteBundleSizeAsync方法
AsyncOperationHandle<long> GetRemoteBundleSizeWithChain(IList<string> bundles)
{
    return ResourceManager.CreateChainOperation(InitializationOperation, op => GetRemoteBundleSizeAsync(key));
}
//通过ab包名得到ab包大小
public AsyncOperationHandle<long> GetRemoteBundleSizeAsync(IList<string> bundles)
{
    //如果还没初始化完那么等待初始化完
    if(!InitializationOperation.IsDone)
        return GetRemoteBundleSizeWithChain(key);
    IList<IResourceLocation> locations = new IList<IResourceLocation>();
    for(var i = 0; i < bundles.Count, i++)
    {
        IList<IResourceLocation> tmpLocations;
        var key = bundles[i];
        //寻找传入的包名对应的ab包,如果没找到那么警告
       if(!GetResourceLocations(key, typeof(object), out locations))
        return ResourceManager.CreateCompletedOperation<Long>(0, new InvalidKeyException(key).Message);
        locations.Add(tmpLocations[0]);
    }
    //总的包大小
    long size = 0;
    for(var i = 0; i < locations.Count; i++)
    {
        if(locations[i].Data != null)
        {
            var sizeData = locations[i].Data as ILocationSizeData;
            if(sizeData != null)
            {
                //计算包大小
                size += sizeData.ComputeSize(locations[i]);
            }
        }
    }
    //返回总的包大小
    return ResourceManager.CreateCompletedOperation<Long>(size, string.Empty)
}
//在对应的Addressables外观类里也添加GetRemoteBundleSizeAsync方法

//使用方法
//在addressable初始化完成后遍历所有地址,如果地址的结尾是.bundle,那么他对应了一个ab包,然后把它缓存到列表,再使用添加的接口来获得所有需要更新包的大小。
Addressables.InitializeAsync().Completed += opHandle =>
{
    var map = opHandle.Result as ResourceLocationMap;
    List<string> bundles = new List<string>();
    foreach (object mapKey in map.keys)
    {
        string key = mapKey as string;
        if(key != null && key.EndsWith(".bundle"))
        {
            bundles.Add(key);
        }
    }
    Addressables.GetRemoteBundleSizeAsync(key).Completed += asyncOpHandle => print(asyncOpHandle.Result);
};

以上就是我对于AB和Addressable资源系统的比较

上一篇 下一篇

猜你喜欢

热点阅读