unity-game-enginecachingofflineassetbundleunitywebrequest

Multiple Asset Bundle Download Cache Problem


I'm using UnityWebRequestAssetBundle.GetAssetBundle(url, bundleData.version, bundleData.crc); system and I can successfully download and use bundleAssets online. But when I want to download multiple bundle assets and save them to use offline for later I have a problem. I have 2 files for example, 'A' and 'B'. Case 1: When I download A and go offline I can load A anytime even I close the app. But when I want to download B and come back to A can't load A again because it deletes cache for some reason and tries to download it again.

Case 2: When I download A and B together and go offline, if I load B it loads. But if I try A it can't load and needs internet connection. After that when I try to load B again I loose package so it needs internet connection again.

So basicly I want to download multiple asset bundles and I want to use them whenever I want. How can I solve this problem? Thanks.

Code example:

using UnityWebRequest uwr = UnityWebRequestAssetBundle.GetAssetBundle(url, bundleData.version, bundleData.crc);
        yield return uwr.SendWebRequest();

            bundle = DownloadHandlerAssetBundle.GetContent(uwr);
            Debug.Log(bundle);

        if (bundle==null)
        {
                Debug.Log("COULDN'T CONNECT TO URL");
                callback(null);
        }
        else
        {
            Debug.Log("FOUND AT SEARCH!");
            // Get downloaded asset bundle
            bundle = DownloadHandlerAssetBundle.GetContent(uwr);
            Sprite sprite = isDiff ? bundle.LoadAsset<Sprite>(levelText + "Diff") : bundle.LoadAsset<Sprite>(levelText);

            callback(sprite);
        }

Solution

  • I solved my issue by saving images to persistentFolder. I write image to disk first by Texture2D.EncodeToJPG();

    private void writeImageOnDisk(Sprite sprite, string fileName)
    {
        Texture2D texture = DeCompress(sprite.texture);
        byte[] textureBytes = texture.EncodeToJPG();
    
        File.WriteAllBytes(Application.persistentDataPath + "/" + fileName+".jpg", textureBytes);
        Debug.Log("File Written On Disk!");
    }
    

    To EncodeToJPG image must be Read/Write enabled before having AssetBundles and you should decompress them first, I found solution from this topic.

    private Texture2D DeCompress(Texture2D source)
    {
        RenderTexture renderTex = RenderTexture.GetTemporary(
                    source.width,
                    source.height,
                    0,
                    RenderTextureFormat.Default,
                    RenderTextureReadWrite.Linear);
    
        Graphics.Blit(source, renderTex);
        RenderTexture previous = RenderTexture.active;
        RenderTexture.active = renderTex;
        Texture2D readableText = new Texture2D(source.width, source.height);
        readableText.ReadPixels(new Rect(0, 0, renderTex.width, renderTex.height), 0, 0);
        readableText.Apply();
        RenderTexture.active = previous;
        RenderTexture.ReleaseTemporary(renderTex);
        return readableText;
    }
    

    And finally you can load image with this code:

    private Sprite loadImageFromDisk(string fileName)
    {
        string dataPath = Application.persistentDataPath + "/" + fileName + ".jpg";
        if (!File.Exists(dataPath))
        {
            Debug.LogError("File Does Not Exist!");
            return null;
        }
    
        byte[] textureBytes = File.ReadAllBytes(dataPath);
        Texture2D loadedTexture = new Texture2D(2048,2048,TextureFormat.ARGB32, false);
        loadedTexture.LoadImage(textureBytes);
        Sprite spr = Sprite.Create(loadedTexture, new Rect(0f, 0f, loadedTexture.width, loadedTexture.height), new Vector2(.5f,.5f), 2048); // 2048 is pixel per unit if you have a custom pixelPerUnit value you should set it here. Or you will see only some part of pixels of image.
        spr.name = fileName;
        return spr;
    }
    

    I hope this will work for you guys. This is how I store my images after downloading assetbundles and how I call them in game.