Addressables不会被卸载

编程语言 2026-07-10

我在研究Addressables时遇到了一个问题。这里展示的代码能够正确地卸载资源(分析器显示处理程序数量为零,状态为无):

[SerializeField] private Image _image;
[SerializeField] private AssetReferenceSprite[] _sprites;

private int _index;
private AsyncOperationHandle<Sprite> _spriteLoadOperation;

private void Update()
{
    if (Input.GetKeyDown(KeyCode.Alpha1))
    {
        SetNextSprite();
    }
}

private void SetNextSprite()
{
    _index = (_index + 1) % _sprites.Length;

    if (_spriteLoadOperation.IsValid())
    {
        _spriteLoadOperation.Completed -= OnLoadSprite;
        _spriteLoadOperation.Release();
    }

    _spriteLoadOperation = _sprites[_index].LoadAssetAsync();
    _spriteLoadOperation.Completed += OnLoadSprite;
}

private void OnLoadSprite(AsyncOperationHandle<Sprite> handle)
{
    _image.sprite = handle.Result;
}

然而,另一种选项(只有在下一个资源加载完成后才卸载资源,而不是立即)并不会卸载资源(分析器显示处理程序为零,但状态仍然是活动的)。

[SerializeField] private Image _image;
[SerializeField] private AssetReferenceSprite[] _sprites;

private int _index;
private AsyncOperationHandle<Sprite> _spriteLoadOperation;
private AsyncOperationHandle<Sprite> _previousSpriteLoadOperation;

private void Update()
{
    if (Input.GetKeyDown(KeyCode.Alpha1))
    {
        SetNextSprite();
    }
}

private void SetNextSprite()
{
    _index = (_index + 1) % _sprites.Length;

    if (_spriteLoadOperation.IsValid())
    {
        _spriteLoadOperation.Completed -= OnLoadSprite;
    }

    _spriteLoadOperation = _sprites[_index].LoadAssetAsync();
    _spriteLoadOperation.Completed += OnLoadSprite;
}

private void OnLoadSprite(AsyncOperationHandle<Sprite> handle)
{
    _image.sprite = handle.Result;

    if (_previousSpriteLoadOperation.IsValid())
    {
        _previousSpriteLoadOperation.Release();
    }

    _previousSpriteLoadOperation = handle;
}

解决方案

Your second version

_image.sprite = handle.Result;

if (_previousSpriteLoadOperation.IsValid())
{
    _previousSpriteLoadOperation.Release();
}

_previousSpriteLoadOperation = handle;

你正在尝试将旧的Sprite保持加载,直到新的一张加载完成。问题如下:

  1. _image.sprite 仍然对 旧的Sprite 保有引用,直到你分配新的一张。
  2. _previousSpriteLoadOperation.Release()_image.sprite 指向新Sprite之后才释放句柄。那部分没问题。
  3. 但旧的句柄实际上仍然是当前指向的 _image.sprite 的同一个对象,因此Addressables会认为它“仍在使用中”。分析器显示 0 handlers(因为你的脚本本身并不持有它),但状态仍然是 Active——Unity仍然把该资源保持活跃,因为Image组件仍然持有它。

所以即便你释放了句柄,该资源本身被 _image.sprite 锁定,直到你分配下一个为止。

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章