c# - Get Hash128 from AssetBundle for the Caching.IsVersionCached function


Keywords:c# 


Question: 

I want to know AssetBundle already in cache. This is usually done with the Caching.IsVersionCached function.

The Caching.IsVersionCached(string url, int version) function overload is no longer supported in Unity 2017.1.

Unity 2017.3 is recommends that I use the Caching.IsVersionCached(string url, Hash128 hash) overload.

I don't know what the Hash128 is and how to obtain and use it. What is Hash128 used for an how do you obtain it from the AssetBundle?


Thank you for your answer.

But I can't solve my problem.

this is my code

for (int i = 0; i < assetInfoList.Count; i++) {

while (!Caching.ready)
    yield return null;


string url = GetUrl(assetInfoList[i].assetbundle_name);
string keyName = url + assetInfoList[i].version_no.ToString(); 

using (UnityWebRequest request = UnityWebRequest.GetAssetBundle(url,(uint)assetInfoList[i].version_no, 0))
{
    if (Caching.IsVersionCached(url, assetInfoList[i].version_no) == true)
        continue;

    if (i == 0)
    {
        string wifiConnectRecommend = Message.Ins.WIFI_ONLY;
        PopUpManager.Instance.PopUp_YesORNoForAssetBundle(wifiConnectRecommend.ToString(), ClickWifi, availableBytes, totalBytes);

        while (!SceneManager.Ins.isWifiUseConfirm)
            yield return null;

    }
    request.SendWebRequest();                

    while (request.isDone == false)
    {
        progressbar.value = request.downloadProgress;
        currentCount.text = countString + " (" + (request.downloadProgress * 100).ToString("N2") + "%)";
        yield return null;
    }

    if (request.error != null)
    {
        Debug.Log("www.error");
    }
    else
    {
        AssetBundleRef abRef = new AssetBundleRef(url, assetInfoList[i].version_no);
        abRef.assetBundle = DownloadHandlerAssetBundle.GetContent(request);

        dictAssetBundleRefs.Add(keyName, abRef);
    }
}

} my purpose is when assetbundle already in cache, go ahead and need to download, set on PopUp_YesORNoForAssetBundle.

hash128 need when check assetbundle downloaded or version check.

but in your explain, hash128 only get after assetbundle loaded or saved manifestfile in resource folder previous time.

I want to know how to check assetbunle is in cache or not.

if you suggest the way, I'm really thanks to you.


1 Answer: 

but I don't know what is hash128

Hash128 represents the hash value of the AssetBundle file that makes it easier to compare AssetBundle file versions when they are downloaded.

I can't find how to use hash128

There is no example on how to do this from the documentation. Below are three ways to obtain Hash128. Which one to use depends on the condition of where the AssetBundle is located and if you want to download it to check the Hash128 or not . In your case, #1 is likely what your are looking for.

1. Obtain Hash128 during AssetBundle build from the Editor then save to the Resources folder:

When building your AssetBundle with the BuildPipeline.BuildAssetBundles function, this function returns AssetBundleManifest. You can obtain Hash128 by using the AssetBundleManifest.GetAssetBundleHash function. Convert the Hash128 to a string with Hash128.ToString() then save it to the Resources folder so that you can access it during run-time.

Example of an Editor build script that will build AssetBundle and save the Hash128 to the Resources folder:

[MenuItem("Assets/Build AssetBundle")]
static void ExportResource()
{
    string folderName = "AssetBundles";
    string filePath = Path.Combine(Application.streamingAssetsPath, folderName);

    AssetBundleManifest assetMf = BuildPipeline.BuildAssetBundles(filePath, BuildAssetBundleOptions.None, BuildTarget.StandaloneWindows64);

    //Get Hash128 from the AssetBundleManifest
    Hash128 hash128 = assetMf.GetAssetBundleHash("AssetBundles");

    //Get the Hash128 as string
    string data = hash128.ToString();
    string path = "Assets/Resources/AssetInfo/AssetBundleInfo.txt";

    //Save the Hash128 to the Resources folder
    using (FileStream fileStream = new FileStream(path, FileMode.Create))
    {
        using (StreamWriter writer = new StreamWriter(fileStream))
        {
            writer.Write(data);
        }
    }
    UnityEditor.AssetDatabase.Refresh();
}

A simple function to load that Hash128 during run-time:

Hash128 getHash128(string path)
{
    //Load from the Resources folder
    TextAsset txtAsset = (TextAsset)Resources.Load(path, typeof(TextAsset));
    string hash128 = txtAsset.text;

    return Hash128.Parse(hash128);
}

How to use:

//Load Hash128 from the Resources folder
Hash128 tempHash128 = getHash128("AssetInfo/AssetBundleInfo");

//Pass to the IsVersionCached function 
Caching.IsVersionCached("yourUrl", tempHash128);

You can also use json to represent and save many as Hash128 as you need.


2. Download the AssetBundle from server then obtain Hash128 during run-time without the Resources folder. Unfortunately, you have to download the AssetBundle first with this method before you can obtain its Hash128. After downloading it, load the data as AssetBundleManifest then obtain Hash128 from it with the AssetBundleManifest.GetAssetBundleHash function. You can then save this Hash128 for later use.

The example below should download and extract Hash128 from an AssetBundle url. No Editor code involved.

IEnumerator downloadAssetBundle(string url)
{
    UnityWebRequest www = UnityWebRequest.GetAssetBundle(url);
    yield return www.SendWebRequest();

    if (www.isNetworkError || www.isHttpError)
    {
        Debug.Log(www.error);
    }
    else
    {
        //Get the AssetBundle
        AssetBundle bundle = DownloadHandlerAssetBundle.GetContent(www);

        AssetBundleRequest asset = bundle.LoadAssetAsync<AssetBundleManifest>("assetManifestName");
        yield return asset;

        //Get the AssetBundleManifest
        AssetBundleManifest loadedAssetMf = asset.asset as AssetBundleManifest;
        //Get Hash128 from the AssetBundleManifest
        Hash128 tempHash128 = loadedAssetMf.GetAssetBundleHash("");

        //Pass to the IsVersionCached function 
        Caching.IsVersionCached("yourUrl", tempHash128);
    }
}

3. Obtain Hash128 from an AssetBundle in the file system. If you already knew the path of the AssetBundle, load the AssetBundle from that path then load the data as AssetBundleManifest and finally obtain Hash128 from it with the AssetBundleManifest.GetAssetBundleHash function. You can then save this Hash128 for later use.

This shows how to load AssetBundle from the StreamingAsset path and obtain its Hash128:

IEnumerator loadAssetManifest(string assetBundleName, string assetManifestName)
{
    string filePath = System.IO.Path.Combine(Application.streamingAssetsPath, "AssetBundles");
    filePath = System.IO.Path.Combine(filePath, assetBundleName);

    var assetBundleCreateRequest = AssetBundle.LoadFromFileAsync(filePath);
    yield return assetBundleCreateRequest;

    AssetBundle asseBundle = assetBundleCreateRequest.assetBundle;

    AssetBundleRequest asset = asseBundle.LoadAssetAsync<AssetBundleManifest>(assetManifestName);
    yield return asset;

    //Get the AssetBundleManifest
    AssetBundleManifest loadedAssetMf = asset.asset as AssetBundleManifest;
    //Get Hash128 from the AssetBundleManifest
    Hash128 tempHash128 = loadedAssetMf.GetAssetBundleHash("");

    //Pass to the IsVersionCached function 
    Caching.IsVersionCached("yourUrl", tempHash128);
}