首页 > 解决方案 > 在编辑器播放模式下显示从 AssetBundle 加载的 Sprite 的问题

问题描述

我正在努力解决 Unity 从 SpriteAtlas 加载 Sprites 的问题,下载到 AssetBundle 中。

在我们当前的游戏中,我正在尝试实现 AssetBundles 以删除“资源”文件夹的使用,并减少内存开销(除其他外)。

在游戏应用程序中,下载的精灵在编辑器中运行时无法正确渲染,因此我构建了一个小型测试项目以更好地理解问题。不幸的是,测试项目运行良好,即使我使用相同的代码来下载和显示精灵。从这里开始,我将这两个版本称为TestAppGameApp。重申一下,这个问题只是在编辑器中运行时出现的问题(不是最终的设备构建),但这对我们来说是一个游戏破坏者,因为我们根本无法开发和测试应用程序。与在编辑器中运行相比,构建到设备的周转时间实在是太长了。

我用于加载资产包的脚本的简化版本如下。(为了简洁起见,这已被大大简化,包括剥离所有对象缓存和错误处理等)

public IEnumerator GetSpriteFromBundle(string bundleURL, string spriteAtlasName, string spriteName, Action<Sprite> onLoadAction)
{
    //  get the AssetBundle
    AssetBundle bundle = null;
    UnityWebRequest request = UnityWebRequestAssetBundle.GetAssetBundle(bundleURL);
    yield return request.SendWebRequest();
    if (!request.isNetworkError && !request.isHttpError)
    {
        bundle = DownloadHandlerAssetBundle.GetContent(request);
    }

    //  Get the SpriteAtlas
    SpriteAtlas atlas = null;
    if (bundle != null)
    {
        if (bundle.Contains(spriteAtlasName))
        {
            AssetBundleRequest assetRequest = bundle.LoadAssetAsync<SpriteAtlas>(spriteAtlasName);
            yield return assetRequest;
            if (assetRequest.isDone)
            {
                atlas = assetRequest.asset as SpriteAtlas;
            }
        }
    }

    //  Get the Sprite
    Sprite sprite = null;
    if (atlas != null)
    {
        sprite = atlas.GetSprite(spriteName);
    }
    onLoadAction(sprite);
}

我用来调用它来加载 Sprite 的脚本如下,(再次删除了错误处理):

public void Start()
{
    UnityEngine.UI.Image displayImage = GameObject.Find("Path/To/ImageObject").GetComponent<UnityEngine.UI.Image>();
    StartCoroutine(
         GetSpriteFromBundle(
            "https://mycdn.com/myassetbundles/gamesprites",      // AssetBundleURL
            "GameSprites",          //    SpriteAssetName
            "Icon1",                      //    SpriteName
            (sprite) =>
            {
                displayImage.sprite = sprite;
            })
        );
}

这样做的最终结果是在 TestApp 中一切正常并正确加载,但是在编辑器中播放 GameApp 时,精灵要么不可见,要么显示为一个奇怪的图像,其中包含 3 个正方形。

我能看到的唯一区别是,当我使用帧调试器查看 TestApp 和 GameApp 之间的差异时,TestApp 会在批处理中显示 SpriteAtlas 纹理,但 GameApp 不会。

正如您在 TestApp 中看到的,纹理设置正确。 TestApp - 纹理设置正确

在 GameApp 中,没有设置纹理 GameApp - 未设置纹理

我在版本之间检查并确认的事情

我可以看到 TestApp 和 GameApp 之间的唯一区别是 GameApp 更大/更复杂,并且它具有场景变化(我们从加载场景开始,然后进入游戏内场景),但我没有'不知道其中任何一个应该如何影响任何事情。

我还使用 AssetBundle.LoadFromFileAsync() 设置并测试了一个版本,并从 StreamingAssets 文件夹加载文件,结果相同

所以,我的问题是:这是 Unity 编辑器中的错误吗?我应该看什么来尝试解决这个问题?在我找到解决方案之前,我们基本上不能使用 AssetBundles。

我已经使用AssetBundleBrowser资产来设置 AssetBundle。

我已经使用各种版本的 Unity 进行了测试,从较旧的 2018.1 版本到最新版本(撰写本文时为 2018.2.7f1)。

(来自Unity 论坛的交叉发布)

- - 更新 - -

有人提到这是一个重复的问题this question,但是我问的是一个完全不同的问题。我的代码在设备上正常工作,但在 Unity 编辑器中不起作用。

我还尝试重组我的代码以查询 Sprite 而不是 SpriteAtlas,并使用 LoadAssetWithSubAssetsAsync 方法和以下代码,我仍然得到相同的最终结果,即编辑器中没有显示精灵。

private IEnumerator GetSpriteFromBundle(string bundleURL, string spriteName, Action<Sprite> onLoadAction)
{
    //  get the AssetBundle
    AssetBundle bundle = null;
    UnityWebRequest request = UnityWebRequestAssetBundle.GetAssetBundle(bundleURL);
    yield return request.SendWebRequest();
    if (!request.isNetworkError && !request.isHttpError)
    {
        bundle = DownloadHandlerAssetBundle.GetContent(request);
    }

    //  Get the Sprite
    Sprite sprite = null;
    if (bundle != null)
    {
        if (bundle.Contains(spriteName))
        {
            AssetBundleRequest assetRequest = bundle.LoadAssetWithSubAssetsAsync<Sprite>(spriteName);
            yield return assetRequest;
            if (assetRequest.isDone)
            {
                for (int i = 0; i < assetRequest.allAssets.Length; i++)
                {
                    sprite = assetRequest.allAssets[i] as Sprite;
                    if (sprite != null && sprite.name == spriteName)
                    {
                        onLoadAction(sprite);
                        yield break;
                    }
                }
            }
        }
    }
    onLoadAction(null);
}

标签: unity3dassetbundle

解决方案


事实证明,问题是由 SpritePacker 设置引起的。

如果我将 SpritePacker 模式(在 Edit->Project Settings->Editor 中)设置为“Enabled for Builds”,则精灵不会正确加载,而如果我将其设置为“Always Enabled”(我相信默认设置),那么sprites,并且 SpriteAtlas 已从 AssetBundle 正确加载。

(我已将此作为 Unity 的错误提出,但尚未收到回复)。


推荐阅读