在编辑器播放模式下显示从AssetBundle加载的精灵的问题

时间:2018-09-25 04:03:31

标签: unity3d assetbundle

我在Unity中从SpriteAtlas加载Sprites时遇到了问题,该资源已从AssetBundle下载。

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

在Game应用程序中,下载的精灵在编辑器中运行时无法正确呈现,因此我构建了一个小型测试项目以更好地理解问题。不幸的是,即使我使用相同的代码来下载和显示精灵,测试项目也能完美地工作。从现在开始,我将这两个版本称为 TestApp GameApp 。重申一下,这个问题只是在编辑器中运行时的问题(不是最终的设备版本),但这对我们来说是一个突破,因为我们根本无法开发和测试应用程序。与在编辑器中运行相比,构建设备所需的周转时间太长了。

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

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中看到的那样,正确设置了Texture。 TestApp - Texture is correctly set

在GameApp中,未设置纹理 GameApp - Texture is not set

我在版本之间检查并确认的内容

  • GameApp和TestApp都没有任何错误或异常。
  • 在构建并部署到设备时,它可以正常工作(仅在 迄今为止的Android)
  • 在GameApp的onLoadAction回调中返回了一个精灵对象。
  • 我在两个应用程序中都使用相同的AssetBundle和Sprites。
  • 我已经在两个应用程序的检查器中对Image对象设置进行了并行比较。
  • 两个应用都设置为相同的构建平台(我尝试使用Android,WebGL和 StandaloneWindows,并且所有结果都相同)
  • AssetBundles是 为正确的构建平台构建(如上所述)

我能看到的TestApp和GameApp之间的唯一区别是GameApp更大/更复杂,而且它的场景有所变化(我们从加载场景开始,然后进入游戏内场景),但我看不出这两个都应该如何影响。

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

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

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

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

(从Unity Forums发来的十字架)

---更新---

有人提到这是一个重复的问题this question,但是我要问一个完全不同的问题。 我的代码在设备上可以正常工作,但在Unity Editor中不能工作。

我还尝试重组代码以查询Sprite而不是SpriteAtlas,并使用LoadAssetWithSubAssetsAsync方法和以下代码,但最终结果仍然相同,即在编辑器中未显示任何Sprite。 / p>

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);
}

1 个答案:

答案 0 :(得分:0)

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

如果我将SpritePacker模式(在“编辑”->“项目设置”->“编辑器”中)设置为“为构建启用”,则不会正确加载该精灵,而如果将其设置为“始终启用”(我相信默认设置) ),然后是精灵,然后从AssetBundle中正确加载了SpriteAtlas。

(我将其作为Unity的一个bug提出,但尚未听到回应)。