原理都懂,总得实践一下吧!
首先得架一个资源服务器,相当于cdn,把自己要更新的资源丢到服务器上。这里服务器采用apache tomcat。
创建一个version.html,内容只有一个数字,相当于远端的更新标记
cdn文件夹里放着所有的资源,需要更新时可以覆盖这个目录
正文开始Addressable
1.安装addressable
2.设置addressable
这两个选项要打上勾哦,切记!
正式打包前一定要勾选这个选项,然后就可以正常构建了,unity在执行BuildPlayer的时候,会默认执行Addressable->Build->New Build->Default Build Script,这样的话就会构建出AA资源,在ServerData/Android目录下,拷贝所有资源到cdn目录
测试更新资源
在Unity中修改资源(注意一定得是可更新的资源,c#脚本是不生效的),本地的版本标记记得需要+1,然后执行Addressable->Build->Update a Previous Build,如此操作会构建出发生改变的资源,同样在ServerData/Android目录下,上传所有资源到cdn,执行覆盖操作,同时服务器上的版本标记需要+1
大功告成了!!!
下边提供核心代码,启动比较一下版本标记,本地的和远端的版本标记进行对比
void Start()
{
UIManager.OnInit();
StartCoroutine(InitGame());
// InitGame();
}
IEnumerator InitGame()
{
yield return Addressables.InitializeAsync();
//获取本地版本标记
var address = Addressables.LoadAssetAsync<VersionConfig>("VersionConfig");
yield return address;
if (address.Status == AsyncOperationStatus.Succeeded)
{
var versionConfig = address.Result;
localFlag = versionConfig.updateFlag;
Debug.Log($"获取本地版本标记:{localFlag}");
}
Addressables.Release(address);
Debug.Log("================");
//获取远程版本标记
yield return GetRemoteVersion();
if (remoteFlag > localFlag)
{
Debug.Log("需要更新资源");
yield return AssetChecker.CheckAsset();
Debug.Log(AssetChecker.isHasUpdate ? "检测到有更新内容" : "没有检测的更新");
if (AssetChecker.isHasUpdate)
{
UIManager.GetInstance().ShowUI("UpdateResUI");
}
else
{
Debug.Log("直接进游戏");
UIManager.GetInstance().ShowUI("LoginUI");
}
}
else
{
Debug.Log("直接进游戏");
UIManager.GetInstance().ShowUI("LoginUI");
}
}
void Update()
{
var progress = AssetChecker.percent;
progressBar.value = progress;
var showPercent = (progress * 100f).ToString("F2");
var cur = (progress * AssetChecker.maxDownLoadSize / 1024f/ 1024f).ToString("F2");
var max = (AssetChecker.maxDownLoadSize / 1024f/ 1024f).ToString("F2");
progressText.text = $"{showPercent}% ({cur}MB/{max}MB)";
}
private void onSureBtnClick()
{
UIManager.GetInstance().ShowUI("LoadingUI");
StartCoroutine(AssetChecker.DownLoad(() =>
{
UIManager.GetInstance().HideUI("UpdateResUI",true);
UIManager.GetInstance().HideUI("LoadingUI",true);
UIManager.GetInstance().ShowUI("LoginUI");
}));
}
以下是检测更新,以及下载的核心代码
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.AddressableAssets.ResourceLocators;
using UnityEngine.ResourceManagement.AsyncOperations;
public class AssetChecker
{
private static readonly List<object> _updateKeys = new List<object>();
public static bool isHasUpdate;
public static long maxDownLoadSize;
public static float percent;
public static IEnumerator CheckAsset()
{
var checkCatalogs = Addressables.CheckForCatalogUpdates(false);
yield return checkCatalogs;
if (checkCatalogs.Status == AsyncOperationStatus.Succeeded)
{
var catalogs = checkCatalogs.Result;
if (catalogs != null && catalogs.Count > 0)
{
var updateCatalogs = Addressables.UpdateCatalogs(catalogs, false);
yield return updateCatalogs;
// 更新列表迭代器
List<IResourceLocator> locators = updateCatalogs.Result;
foreach (var locator in locators)
{
_updateKeys.AddRange(locator.Keys);
// key 里一堆乱七八糟的东西
}
Addressables.Release(updateCatalogs);
}
}
Addressables.Release(checkCatalogs);
AsyncOperationHandle<long> sizeHandle = Addressables.GetDownloadSizeAsync(_updateKeys as IEnumerable<object>);
yield return sizeHandle;
maxDownLoadSize = sizeHandle.Result;
isHasUpdate = maxDownLoadSize > 0;
}
public static IEnumerator DownLoad(Action callback)
{
AsyncOperationHandle downHandle = Addressables.DownloadDependenciesAsync(_updateKeys as IEnumerable<object>, Addressables.MergeMode.Union, false);
while (!downHandle.IsDone)
{
percent = downHandle.GetDownloadStatus().Percent;
yield return null;
}
yield return downHandle;
if (downHandle.Status != AsyncOperationStatus.Succeeded)
{
Debug.LogError("下载失败 - 重新尝试下载");
Addressables.Release(downHandle);
yield break;
}
else
{
Addressables.Release(downHandle);
Debug.Log("下载完成,进入游戏");
callback.Invoke();
}
}
}
只是简单的测试,可能有考虑不周或者书写有误的地方,欢迎指正!