【Unity】热更新学习笔记-Addressable

本地Addressables使用

Group配置

加载资源

1
2
3
4
5
6
7
8
9
10
11
12
public class LoadSprite : MonoBehaviour
{
[SerializeField] private AssetReferenceSprite sprite;

private IEnumerator Start()
{
var spHandle = sprite.LoadAssetAsync<Sprite>();
yield return spHandle;
GetComponent<Image>().sprite = spHandle.Result;
Addressables.Release(spHandle); // 不规范写法,应写在OnDestroy中
}
}

开始游戏后成功屏幕中间的白方块变成单手剑

如果直接引用资源,在游戏启动的时候就会加载该资源(如果资源很多就会卡很久),且该资源会一直存在游戏生命周期内。

本地使用Addressables的优点:

  • 不会在场景开始的时候就加载该资源,而是会等到真正使用的时候加载
  • 可以手动释放该资源占用内容,减少内存压力。

详情测试观看How to use Addressables FASTER Loading FREE Memory SMALL Download

  • 4:05:基础Instantiate()方法加载预制体,启动游戏时间需20秒;且未创建物体时就已经占用内存了。
  • 11:25:Addressable方法加载预制体,启动游戏时间只需2秒;未创建物体时没有占用内存,只有当物体加载出来时才会占用内存。

所以,为了优化游戏,不管你是否需要热更新,最好使用Addressables加载资源,而不是常规方式

真实环境测试

上方的代码直接运行是没有问题的,因为此时unity是直接从Assets Databse(也就是资产路径中)获取资产

为了模拟真实的用户环境,需要如下设置

此时运行游戏会发现:剑只出现了一帧,然后又变成了白方块

原因:Addressables.Release(spHandle)的时候释放了weapon这个图片,所以Image在内存中也找不到该图片。

1
2
3
4
5
6
7
8
9
10
11
12
13
// 正确的写法:
AsyncOperationHandle<Sprite> spHandle; // 声明为字段
private IEnumerator Start()
{
spHandle = sprite.LoadAssetAsync<Sprite>();
yield return spHandle;
GetComponent<Image>().sprite = spHandle.Result;
Debug.Log(spHandle.Result == null);
}
private void OnDestroy()
{
Addressables.Release(spHandle); // 手动释放,减少GC压力
}

远程Addressables使用

配置

添加新的路径配置

添加远程Group。不要删掉Local Group!!!!!!

设置为Pack Separately时,从上图可以看出来,虽然Remote组下有三个物体,但是依然只会生成两个文件。因为我们是添加了两个文件夹在Group中。

Addressable设置

此时如果在Use Existing Build模式下将无法启动unity,且会报错。因为并没有构建Addressables资产,先Build -> New Build -> Default build Script一份吧。

1
Player content must be built before entering play mode with packed data.  This can be done from the Addressables window in the Build->Build Player Content menu command.

将资产上传服务器

构建之后,直接启动unity也会报错,且图片不显示。因为我们并没有将物体放置到服务器上。看起来这是很理所当然的事情。但这里我需要强调的是:在物体进入到了Group之后,该物体就不访问本地,而只能访问远程的了。因为本地根本就不存在该资产

1
2
3
4
RemoteProviderException : Unable to load asset bundle from : https://www.coffeeofnosugar.top/addressable/c15f93f7cc4db145f53ace35f7416bfa.bundle
UnityWebRequest result : ProtocolError : HTTP/1.1 404 Not Found
ResponseCode : 404, Method : GET
url : https://www.coffeeofnosugar.top/addressable/c15f93f7cc4db145f53ace35f7416bfa.bundle

上传服务器

此时启动unity,就能看到单手剑了

注意:

从服务器获取到的资源会缓存到本地,这时我们再次启动游戏,游戏不会向服务器发送请求

可以使用Everything找到该缓存,删除后再测试一遍,缓存名称为.bundle文件的哈希值

如此也从侧面的证明了,该资产确实是从服务器获取到的

实现热更

将单手剑替换成锤子,在Explorer中直接替换文件

更新包体

此时,你会发现ServerData/StandaloneWindow64中多了一个文件,将其上传到服务器上

重新打开游戏,热更成功。


调试

Ctrl+7唤出性能调试面板

就拿前面的Addressables.Release(spHandle);举例


总结

  1. Addressables十分强大,不管是否需要使用热更,最好都使用Addressable管理资源
  2. 直接将所有资产都放到Remote Group下肯定是不理想的,这样一来所有资产都需要从网上拉取。(但有的手游每次大更新的时候都需要下载很长的一条内容,原因应该正是如此。)能否有更好的方法能减少服务器压力呢,请看下一篇文章。